The topic of security covers many different facets within the SDLC. From focusing on secure application design to designing systems to protect computers, data, and networks against potential attacks, it is clear that security should be top of mind for all developers. This Zone provides the latest information on application vulnerabilities, how to incorporate security earlier in your SDLC practices, data governance, and more.
Lots of companies are eager to provide their identity provider: Twitter, Facebook, Google, etc. For smaller businesses, not having to manage identities is a benefit. However, we want to avoid being locked into one provider. In this post, I want to demo how to use OpenID Connect using Google underneath and then switch to Azure. OpenID Connect The idea of an authorization open standard started with OAuth around 2006. Because of a security issue, OAuth 2.0 superseded the initial version. OAuth 2.0 became an IETF RFC in 2012: The OAuth 2.0 authorization framework enables a third-partyapplication to obtain limited access to an HTTP service, either onbehalf of a resource owner by orchestrating an approval interactionbetween the resource owner and the HTTP service, or by allowing thethird-party application to obtain access on its own behalf - RFC 7469, The OAuth 2.0 Authorization Framework OAuth focuses mostly on authorization; the authentication part is pretty light: it contains a section about Client Password authentication and one Other Authentication Methods. The authorization server MAY support any suitable HTTP authenticationscheme matching its security requirements. When using otherauthentication methods, the authorization server MUST define amapping between the client identifier (registration record) andauthentication scheme. - 2.3.2. Other Authentication Methods OpenID Connect uses OAuth 2.0 and adds the authentication part: OpenID Connect 1.0 is a simple identity layer on top of the OAuth 2.0 protocol. It allows Clients to verify the identity of the End-User based on the authentication performed by an Authorization Server, as well as to obtain basic profile information about the End-User in an interoperable and REST-like manner. OpenID Connect allows clients of all types, including Web-based, mobile, and JavaScript clients, to request and receive information about authenticated sessions and end-users. The specification suite is extensible, allowing participants to use optional features such as encryption of identity data, discovery of OpenID Providers, and logout, when it makes sense for them. - "What is OpenID Connect?" Here are a couple of identity providers that are compatible with OpenID Connect: GitHub Google Microsoft Apple Facebook Twitter Spotify In the following, we will start with Google and switch to Azure to validate our setup. Setting up OpenID Connect With Apache APISIX Imagine we have a web app behind Apache APISIX that we want to secure with OpenID Connect. Here's the corresponding Docker Compose file: YAML version: "3" services: apisix: image: apache/apisix:3.1.0-debian #1 ports: - "9080:9080" volumes: - ./apisix/config.yml:/usr/local/apisix/conf/config.yaml:ro #2 - ./apisix/apisix.yml:/usr/local/apisix/conf/apisix.yaml:ro #3 env_file: - .env httpbin: image: kennethreitz/httpbin #4 Apache APISIX API Gateway APISIX configuration - used to configure it statically in the following line Configure the single route. Webapp to protect - any will do Apache APISIX offers a plugin-based architecture. One such plugin is the openid-connect plugin, which allows using OpenID Connect. Let's configure it: YAML routes: - uri: /* #1 upstream: nodes: "httpbin:80": 1 #1 plugins: openid-connect: client_id: ${{OIDC_CLIENTID} #2 client_secret: ${{OIDC_SECRET} #2 discovery: https://${{OIDC_ISSUER}/.well-known/openid-configuration #2-3 redirect_uri: http://localhost:9080/callback #4 scope: openid #5 session: secret: ${{SESSION_SECRET} #6 #END Catch-all route to the underlying web app Plugin configuration parameters - Values depend on the exact provider (see below). OpenID Connect can use a Discovery endpoint to get all necessary OAuth endpoints. See OpenID Connect Discovery 1.0 spec for more information Where to redirect when the authentication is successful - It mustn't clash with any of the explicitly defined routes. The plugin creates a dedicated route there to work its magic. Default scope Key to encrypt session data - Put whatever you want. Configuring Google for OIDC Like all Cloud Providers, Google offers a full-fledged Identity Management solution, which may be daunting for newcomers. In this section, I'll only detail the necessary steps required to configure it for OIDC. On the Cloud Console, create a dedicated project (or use an existing one). If you didn't do it already, customize the OAuth Consent Screen. In the project context, navigate APIs & Services/Credentials. Then, press the + CREATE CREDENTIALS button in the upper menu bar. Select OAuth Client Id in the scrolling menu. Fill in the fields: Application type: Web application Name: Whatever you want Authorized redirect URIs: /callback, e.g., http://localhost:9080/callback URL should be the URL of the web application. Likewise, /callback should match the openid-connect plugin configuration above. Note that Google doesn't allow relative URLs, so if you need to reuse the application in different environments, you need to add the URL of each environment. Click the Create button. In the Docker Compose configuration above, use the Client ID and Client Secret as OIDC_CLIENTID and OIDC_SECRET. I wrote them down as environment variables in a .env file. The last missing variable is OIDC_ISSUER: it's accounts.google.com. If you navigate to this page, you'll see all data required by OAuth 2.0 (and more). At this point, we can start our setup with docker compose up. When we navigate to http://localhost:9080/, the browser redirects us to the Google authentication page. Since I'm already authenticated, I can choose my ID - and I need one bound to the organization of the project I created above. Then, I can freely access the resource. Configuring Azure for OIDC My colleague Bobur has already described everything you need to do to configure Azure for OIDC. We only need to change the OIDC parameters: OIDC_CLIENTID OIDC_SECRET OIDC_ISSUER: On Azure, it should look something like login.microsoftonline.com//v2.0. If you restart Docker Compose with the new parameters, the root page is now protected by Azure login. Conclusion Externalizing your authentication process to a third party may be sensible, but you want to avoid binding your infrastructure to its proprietary process. OpenID Connect is an industry standard that allows switching providers easily. Apache APISIX offers a plugin that integrates OIDC so that you can protect your applications with the latter. There's no reason not to use it, as all dedicated identity providers, such as Okta and Keycloak, are OIDC-compatible. The complete source code for this post can be found on GitHub. To Go Further: OpenID Connect Discovery 1.0 specification Apache APISIX OIDC plugin Use Keycloak with API Gateway to secure APIs How to Use Apache APISIX Auth With Okta
Setting up a VPN server to allow remote connections can be challenging if you set this up for the first time. In this post, I will guide you through the steps to set up your own VPN Server and connect to it using a VPN Client. Additionally, I will also show how to set up a free Radius server and a plugin to implement multi-factor authentication for additional security. 1. Installation OpenVPN Server on Linux (Using a Centos Stream 9 Linux) # yum update # curl -O https://raw.githubusercontent.com/angristan/openvpn-install/master/openvpn-install.sh # chmod +x openvpn-install.sh # ./openvpn-install.sh Accept defaults for installation of OpenVPN and, in the end, provide a Client name e.g. demouser. I have chosen a passwordless client, but if you want, you can also add an additional password to protect your private key. PowerShell Client name: demouser Do you want to protect the configuration file with a password? (e.g. encrypt the private key with a password) 1) Add a passwordless client 2) Use a password for the client Select an option [1-2]: 1 ... ... The configuration file has been written to /root/demouser.ovpn. Download the .ovpn file and import it in your OpenVPN client. Finally, a client configuration file is ready to be imported into the VPN Client. 2. Installation of OpenVPN Client for Windows Download the OpenVPN Client software. Install the OpenVPN Client: Once the installation is finished, we can import the configuration file demouser.ovpn which was generated on the OpenVPN server, but before importing, we need to modify the IP address of our OpenVPN server within this file: client proto udp explicit-exit-notify remote 192.168.0.150 1194 dev tun resolv-retry infinite nobind persist-key persist-tun ... Normally the remote IP by default will be the address of your public IP which is normal if you have your VPN server on your local network and need remote access from outside this network. You can leave the public IP address in the config, but then you will have to open up the correct port and set the routing on your internet access point. Finally, we can test the VPN connection. The first time the connection will probably fail as the firewall on the OpenVPN Linux server is blocking the access. To quickly test this, we can just disable the firewall using the command: # systemctl stop firewalld Alternatively, configure Linux firewall for OpenVPN connectivity: # sudo firewall-cmd --add-service=openvpn # sudo firewall-cmd --permanent --add-service=openvpn # sudo firewall-cmd --add-masquerade # sudo firewall-cmd --permanent --add-masquerade # sudo firewall-cmd --permanent --add-port=1194/udp # sudo firewall-cmd --reload Now the connection should work: On the windows client, you should now also get an additional VPN adapter configured with a default IP address of 10.8.0.2 (this subnet is defined within the file /etc/openvpn/server.conf). 3. How To Use Radius With OpenVPN First, we will install the IBM Security Verify Gateway for Radius on a Windows machine. This package can be downloaded from the IBM Security AppExchange (you will need to use your IBMid to log in). Extract and run the installation using setup_radius.exe. Edit the Radius configuration file c:\Program Files\IBM\IbmRadius\IbmRadiusConfig.json: Find the clients section in the configuration file. The default file has three example client definitions. Delete these definitions and replace them with the single definition shown above. This definition will match any Radius client connecting from the network used by the test machines. The secret authenticates the client. Save the file and close the editor. JSON { "address":"::", "port":1812, /* "trace-file":"c:/tmp/ibm-auth-api.log", "trace-rollover":12697600, */ "ibm-auth-api":{ "client-id":"???????", "obf-client-secret":"???????", /* See IbmRadius -obf "the-secret" */ "protocol":"https", "host":"???????.verify.ibm.com", "port":443, "max-handles":16 }, "clients":[ { "name": "OpenVPN", "address": "192.168.0.0", "mask": "255.255.0.0", "secret": "Passw0rd", "auth-method": "password-and-device", "use-external-ldap": false, "reject-on-missing-auth-method": true, "device-prompt": "A push notification has been sent to your device:[%D].", "poll-device": true, "poll-timeout": 60 } ] } Complete the fields client-id, obf-client-secret and host with the correct information to point to your IBM Verify Saas API. Before we can do this, we will need to set up API access in IBM Verify Saas. Login to your environment or go for a trial account if you don’t have one. From the main menu, select Security > API Access > Add API client Create a new API Client : Specify the entitlements by selecting the check bow from the list: Authenticate any user Read authenticator registrations for all users Read users and groups Read second-factor authentication enrollment for all users Click next on the following screens and finally give the API client a name: e.g. MFA-Client A Client ID and Secret will automatically be created for you. Use this information to complete the Radius config. Use the c:\Program Files\IBM\IbmRadius\IbmRadius.exe -obf command to generate the obfuscated secret value. Finally, configure the IBM Radius service to startup automatically and start the service: Test Radius Authentication using the Radius tool : NTRadPing You should get a push notification on the IBM Verify app on the mobile device. (Make sure you test with a userid that is known in IBM Verify Saas and is enrolled for OTP) 4. Install OpenVPN Radius Plugin Log in to the Linux OpenVPN server and launch the following commands: # wget https://www.nongnu.org/radiusplugin/radiusplugin_v2.1a_beta1.tar.gz # tar -xvf radiusplugin_v2.1a_beta1.tar.gz # cd radiusplugin_v2.1a_beta1 # yum install libgcrypt libgcrypt-devel gcc-c++ # make Copy the Radius plugin files to /etc/openvpn # cp /root/radiusplugin_v2.1a_beta1/radiusplugin.cnf /etc/openvpn # cp /root/radiusplugin_v2.1a_beta1/radiusplugin.so /etc/openvpn Edit the file /etc/openvpn/server.conf and add the following line to activate the Radius plugin: plugin /etc/openvpn/radiusplugin.so /etc/openvpn/radiusplugin.cnf Edit the file /etc/openvpn/radiusplugin.cnf and modify the ip address of the Radius server and set the sharedsecret to Passw0rd (this is the secret that was also configured on the Radius server side). Make sure to set nonfatalaccounting=true because the Radius server does not support Radius accounting. C ... NAS-IP-Address=<IP Address of the OpenVPN Server> ... nonfatalaccounting=true ... Server { # The UDP port for RADIUS accounting. acctport=1813 # The UDP port for RADIUS authentication. authport=1812 # The name or ip address of the RADIUS server. name=<IP Address of the RADIUS Server> # How many times should the plugin send the if there is no response? retry=1 # How long should the plugin wait for a response? wait=60 # The shared secret. sharedsecret=Passw0rd } Save the file and restart the OpenVPN server using the command : # systemctl restart openserver-server@server.service Finally, edit the OpenVPN client file demouser.ovpn and add a line auth-user-pass : client proto udp auth-user-pass explicit-exit-notify remote 192.168.0.150 1194 dev tun resolv-retry infinite nobind persist-key persist-tun ... This will allow the user to enter a username and password when initiating the VPN connection. These credentials will be authenticated against the IBM Verify Saas directory, and this should result in a challenge request on the IBM Verify Mobile app. The wait=60 will allow the plugin to wait for a response from the user who has to respond to the challenge using the IBM Verify App on his phone. If you prefer to use a TOTP challenge instead, you can modify the Radius configuration file on Windows (IBMRadiusConfig.json) and set the auth-method to password-and-totp. Then you can open the client VPN connection and use 123456:password instead of the normal password.
For the first time since 2019, the "world's largest developer and engineering expo" was back in person, this time in Oakland in February: DeveloperWeek 2023! Approximately 2000 attendees, speakers, and exhibitors got together face to face to meet and talk about the state of the software industry. People came from all over the world to be part of this 15+ track event that covered everything from application and API design, to Kubernetes and Terraform deployment fundamentals, and basically everything in between. I got to give a talk as well on the state of cloud development environments, which I have written about here before. There was a noticeable thread around cybersecurity throughout all the tracks. As security becomes more and more of a focus for the enterprise, it should be no surprise to see so many talks about securing your data and your applications. Here are just a few highlights from some of the sessions centered around security from DeveloperWeek 2023. Securing Your Applications and APIs Secure Your APIs There is a lot you could cover about application security, but one particular topic popped up in several talks, API security. There were two talks on this matter from slightly different perspectives, and I think both approaches are worth looking into, so I am highlighting them here. The first session was a holistic approach from Farshad Abasi, Founder and CEO of Forward Security, in his talk "Designing Secure API and Microservices-Based Applications." He explained the history of Service Oriented Architecture. We think of "web APIs" when we think of Application Programming Interfaces, but APIs have been around for a very long time. He talked about the transformation at IBM, which went from 1000s of independent applications, all reinventing the wheel to recognizing there were multiple overlapping services underlying every application and starting to deploy addressable services. Farshad shared that in those early days, heavy-weight solutions like SAML and SOAP worked well behind firewalls, but soon, the rise of web applications and open networks drove HTTP and JSON as the new standards. With this change, we lost the benefit of the single entry into the "trust zone" where monolithic applications and service-oriented architecture, SOA deployments ran. Running safe microservices means we can trust no one and need to authenticate all the way through for every request. At the heart of his session, he explained how API gateways should act as a single point of entry into your application, giving you an isolated service to handle both authentication and authorization. Both of those jobs are related, but he spent some time explaining the difference. Authorization vs. Authentication To make it easier to conceptualize, he suggested thinking about the real-world example of a bouncer at a fancy nightclub. When you first arrive, the bouncer asks for your ID, normally some government-issued document, such as a driver's license or passport. At this stage, the authenticity of the ID is scrutinized to make sure it is legit and not a forged document. The contents are normally confirmed as well, sometimes by the bouncer asking you questions and verifying the answers. This is the authentication process, often abbreviated as AuthN.Once the bouncer confirms you are who you say you are, they proceed to make sure you are supposed to be there by consulting the guest list. If your name is on the list, then you are authorized to go in. This is the authorization process, abbreviated as AuthZ.API gateways can help with both AuthN and AuthZ by examining requests for authenticity and checking for the correct signatures or certificates and then consulting access controls to ensure only the right requests get through. Just because you have a valid ID does not mean you get full access to all the DBs and servers.This approach assumes you are starting with Zero Trust in mind, granting the least privileges possible to allow work to be performed. Farshad wrapped up his talk by talking about the importance of logging, including monitoring and reviewing them consistently. The earlier you take into account how you will deal with AuthN, AuthZ, permissions, and logging, the safer your application will be as you move it toward production. API Security and OWASP Thinking about API security from early in the design process is an excellent idea, but it can be challenging to know where to start when dealing with an existing or legacy system where you want to update security. This is where the approach from Colin Domoney, Chief Technology Evangelist at 42Crunch, really comes into its own. In his session "Everything You Need to Know About API Security," he walked us through the OWASP API Top 10. While there is some crossover from the OWASP Top 10 standard awareness project, the API Top 10 focuses on the unique vulnerabilities and security risks that the API brings. Colin walked us through the list, and the vulnerabilities at play then shared some industry horror stories that highlighted what can go wrong. In one of the more amusing stories, a microbrewery forgot to lock down the testing credentials that let users get unlimited beer tokens. In another, more widespread example, a WordPress plugin gave full site admin rights to any user who knew how to access the plugin's control panel through URL manipulation — a good reminder to always only grant the least privileges by default. Scaling Safely, Even When Your Apps Are Under Attack In his talk "Your Apps Are Under Attack," Cory Gideon Manager Consultant at Sogeti USA, wasted no time in getting to the point that security is hard and takes work. While it might be tempting to think you can just buy a single product to make you unhackable, the reality is no single vendor can deliver on such a promise. This is partly due to the pace of evolving threats combined with the complexity and size of our applications. He also shared some sobering stats: 36% of devs surveyed attributed priority of meeting deadlines as to why code still contains vulnerabilities 33% admitted that they don't know what makes their code vulnerable 30% said their in-house security training could be improved with practical real-world examples. 30% said their biggest concern with implementing secure coding is dealing with vulnerabilities introduced by co-workers. When something goes wrong, many teams just fire up that blamethrower. Fortunately, Cory shared a lot of straightforward best practices and open source tools that can help us all work more securely while still meeting our deadlines. This starts with securing our password policies. He shared a project called changeme that can detect default and backdoor credentials throughout any system. He also urged teams to review their stacks for deprecated protocols and encryption strategies, as they become obsolete for a reason.When focusing on points of access, he said it is important to understand attackers have two critical jobs, 1) get in and 2) get out. If you can disrupt either of those, you can buy time to act. This is where honeytokens would be helpful as well.There are basically too many good suggestions to list here, but fortunately, Cory shared that OWASP has already laid all of this out in their CheatSheet series, which you should check out. The last points he made were around ChatGPT and some of the potential ways it is already changing security. Cory believes that attackers are already asking ChatGPT to help them and we should be too if we want to keep up in the fight. Toward the end, he shared one of my favorite quotes from the whole event: ChatGPT will not take your job. A developer who knows how to use ChatGPT will. Beyond just securing your application architecture, developers also need to worry about the issues when you deploy and then try to scale your application. That was the very subject Kerim Satirli, Senior developer advocate at HashiCorp, covered in his talk "Scaling Security when Deploying Globally." At the core of his talk, Kerim told us that "security is a team sport" that requires us all to automate as much as possible and educate everyone on best practices.He shared that 10% of companies still say they use Root access for things daily. While most of us know we shouldn't do that, it is up to all of us to make sure everyone knows that. Another thing we need to do better around is Zero Trust. Kerim encourages us to think about the default access policy as "deny," so "if the power goes out, all the doors remain locked."Another topic he brought up was locking out unneeded regions. For example, if you have your whole infrastructure in AWS zone us-east-2, there is no reason you should leave it open to requests from ap-east-1 or eu-central-2, to just pick a couple at random.He also spent some time enumerating the advantages of short-lived dynamic secrets. The best secrets are the ones that never get shared; that way, they can never be hardcoded, which we here at GitGuardian wish happened less than it does. Securing Your Data While securing the code and your environments is certainly an important part of a mature security posture, if you are careless with your data, then you are just as vulnerable to catastrophe. In their session "Don’t DIY PII. Five Data Privacy Challenges and How to Solve Them," the team from Skyflow, Sean Falconer, Head of Developer Relations, and Manish Ahluwalia, Technology Executive, shared that one of the main reasons that large companies have seen so many breaches is because they hold so much customer personal identifying information, PII. This is extremely valuable to bad actors. Once an attacker has enough data points, they can launch spear phishing attacks or, worse, steal the customer's identity.They summed up 5 data privacy challenges that you need to consider when dealing with PII: 1. Secure storage: Knowing where your PII rests has the right encryption.2. Access controls: Knowing who has access to PII at any given point.3. The right to be forgotten: Knowing where all the PII lives so you can remove all PII when needed.4. Residency: Knowing all the laws about any geographical region or state where PII lives.5. Secure data utilization: Knowing what systems are accessing your data and that all those services are secure.They talked about possible solutions where real PII or other sensitive data is never actually stored in the DB or inside applications, instead storing those data points in secure data vaults. Data vaults can safely and securely store sensitive data and generate pointers to the real data, which can be safely stored in DBs and open applications with no fear of real data leakage. Endpoints that need to ingest the real data can get it from the vaults; otherwise, they get served the pointers which have no value without the right access rights. No matter what solution you find is right for your architecture, addressing those five main points will help you get on the path to better data security. Even if we have our data locked down and we personally trust the security, how do we objectively know if we can trust it? That was at the heart of the session from Soumen Chatterjee, Associate Vice President at HCLTech CloudSMART. In his talk "Building the Data Trust on Cloud – Confidential Computing, Sovereign Cloud, and Secure Cloud," he brought up that we have spent a lot of time securing our data encryption at rest and in transit. But when it comes to data in use, we mostly just adopt a 'magical trust' philosophy that assumes the app itself must be secure. This is as true of Gmail as it is of a healthcare portal, though we know these are very different applications.Soumen says we need a standard for data governance in the cloud, a way that will lead to trusted applications. He spelled out Five Elements of a Sovereign cloud: Data sovereignty Data localization Data ownership Data traceability Data access controls While there is no single magic bullet to grant trust for your application, if your cloud-based solution can answer all of those points, then you are on a good path. While insecure data can cost your company a lot in the case of a breach, Shailvi Wakhlu, Former Head of Data & Analytics at Strava, says bad data is costing your company a lot right now. While not expressly a security talk, her session "Preventing, Diagnosing & Curing Bad Data" provided great insight into data issues I think can be applied by development and security teams. By "bad data," she means any data that is inaccurate, incomplete, or misleading. Bad data leads to biased decision-making, which will always lead to worse outcomes. From a security perspective, it means you can be overoptimizing for the wrong vulnerabilities. In marketing, it means you might be undercharging for your services, leading to a failed business in the worst extremes. Ultimately though, bad data can lead to legal issues and terrible employee morale; no one loves dealing with data they need to clean up continually.To identify and fix bad data, she laid out the flow of data creation, ingestion, and usage to help identify where issues arise. According to Shailvi, all data gets: Defined Logged and stored Transformed, such as when we apply business rules to it Analyzed Shared At each step, the chance for data corruption arises, and the earlier we can catch issues, the easier it is to solve in the long term. To illustrate her point about data aggregation and how human bias seeps in, she showed a picture of a set of ingredients, including butter, eggs, flour, salt, and some bowls. If you asked some people what they were making in the picture, some would guess pancakes, some would guess bread, and some would guess something else. The data simply showed ingredients, but if someone who labels the picture inserts their bias into the label, we might mislabel this as a pancake instead of what it really is. While she would love a world of perfect data, she also said it is important to take into consideration the criticality of the data and the scope of attempting to clean it all up versus just focusing on where you can help. She summed it up very well with this paraphrased quote: When you encounter bad data, you have to consider; should keep sweeping the floors or should we burn the building down? DeveloperWeek Is Helping Us All Dev Better This article barely scratches the surface of all the amazing sessions at DeveloperWeek. Beyond the talks and workshops, this event was meaningful in bringing a large and diverse community back together face-to-face. The hallway conversations, the shared experiences at the toss-across and tic-tac-toe lounge, and the memories will last no matter what the AI revolution brings our way. At the end of the day, software is made by people. This was a great event for those people to share their passion and knowledge. I am already looking forward to DeveloperWeek 2024!If you were not able to attend in person, DeveloperWeek continues online in the virtual event portion. Check out the DeveloperWeek website for more info on how to watch the recordings from the virtual event.
What Is SIEM? SIEM stands for Security Information and Event Management. It is a software solution that provides real-time analysis of security alerts generated by network hardware and applications. SIEM collects log data from multiple sources such as network devices, servers, and applications, then correlates and analyzes this data to identify security threats. SIEM can help organizations improve their security posture by providing a centralized view of security events across the entire IT infrastructure. It allows security analysts to quickly identify and respond to security incidents and provides detailed reports for compliance purposes. Some of the key features of SIEM solutions include: Log collection and analysis Real-time event correlation and alerting User and entity behavior analytics Threat intelligence integration Compliance reporting SIEM is often used in conjunction with other security solutions, such as firewalls, intrusion detection systems, and antivirus software, to provide comprehensive security monitoring and incident response capabilities. What Is ELK? ELK is an acronym for a set of open-source software tools used for log management and analysis: Elasticsearch, Logstash, and Kibana. Elasticsearch is a distributed search and analytics engine that provides fast search and efficient storage of large volumes of data. It is designed to be scalable and can handle a large number of queries and indexing operations in real-time. Logstash is a data collection and processing tool that allows you to collect logs and other data from multiple sources, such as log files, syslog, and other data sources, and transform and enrich the data before sending it to Elasticsearch. Kibana is a web-based user interface that allows you to visualize and analyze data stored in Elasticsearch. It provides a range of interactive visualizations, such as line graphs, bar charts, and heatmaps, as well as features such as dashboards and alerts. Together, these three tools form a powerful platform for managing and analyzing logs and other types of data, commonly referred to as the ELK stack or Elastic stack. The ELK stack is widely used in IT operations, security monitoring, and business analytics to gain insights from large amounts of data. Ingesting SIEM Data to ELK Ingesting SIEM data into the ELK stack can be useful for organizations that want to combine the security event management capabilities of SIEM with the log management and analysis features of ELK. Here are the high-level steps to ingest SIEM data into ELK: Configure the SIEM to send log data to Logstash, which is part of the ELK stack. Create a Logstash configuration file that defines the input, filters, and output for the SIEM data. Start Logstash and verify that it is receiving and processing SIEM data correctly. Configure Elasticsearch to receive and store the SIEM data. Create Kibana visualizations and dashboards to display the SIEM data. Here is an example of a Logstash configuration file that receives Syslog messages from a SIEM and sends them to Elasticsearch: Python input { syslog { type => "syslog" port => 5514 } } filter { if [type] == "syslog" { grok { match => { "message" => "%{SYSLOGTIMESTAMP:syslog_timestamp} %{SYSLOGHOST:syslog_hostname} %{DATA:syslog_program}(?:\[%{POSINT:syslog_pid}\])?: %{GREEDYDATA:syslog_message}" } add_field => [ "received_at", "%{@timestamp}" ] add_field => [ "received_from", "%{host}" ] } } } output { elasticsearch { hosts => ["localhost:9200"] index => "siem" } } Once Logstash is configured and running, SIEM data will be ingested into Elasticsearch and can be visualized and analyzed in Kibana. It's important to ensure that the appropriate security measures are in place to protect the SIEM and ELK environments, and to monitor and alert on any security events. Detecting Host Hack Attempt Detecting host hack attempts using SIEM in ELK involves monitoring and analyzing system logs and network traffic to identify suspicious activity that may indicate a hack attempt. Here are the high-level steps to set up host hack attempt detection using SIEM in ELK: Configure the hosts to send system logs and network traffic to a centralized log collection system. Set up Logstash to receive and parse the logs and network traffic data from the hosts. Configure Elasticsearch to store the parsed log data. Use Kibana to analyze the log data and create dashboards and alerts to identify potential hack attempts. Here are some specific techniques that can be used to detect host hack attempts: Monitor for failed login attempts: Look for repeated failed login attempts from a single IP address, which may indicate a brute-force attack. Use Logstash to parse the system logs for failed login events and create a Kibana dashboard or alert to monitor for excessive failed login attempts. Monitor for suspicious network traffic: Look for network traffic to or from known malicious IP addresses or domains. Use Logstash to parse network traffic data and create a Kibana dashboard or alert to monitor for suspicious traffic patterns. Monitor for file system changes: Look for unauthorized changes to system files or settings. Use Logstash to parse file system change events and create a Kibana dashboard or alert to monitor for unauthorized changes. Monitor for suspicious process activity: Look for processes that are running with elevated privileges or that are performing unusual actions. Use Logstash to parse process events and create a Kibana dashboard or alert to monitor for suspicious process activity. By implementing these techniques and regularly monitoring the logs and network traffic, organizations can improve their ability to detect and respond to host hack attempts using SIEM in ELK. Configure Alert in ELK to Detect Host Hack Attempt To configure an alert in ELK to detect a host hack attempt, you can follow these general steps: Create a search query in Kibana that filters logs for Host Hack Attempt events. For example, you can use the following search query to detect failed login attempts: Python from elasticsearch import Elasticsearch es = Elasticsearch() search_query = { "query": { "bool": { "must": [ { "match": { "event.dataset": "auth" } }, { "match": { "event.action": "failed_login" } } ] } } } res = es.search(index="siem", body=search_query) for hit in res['hits']['hits']: print(hit['_source']) Once you have created your search query, save it as a Kibana saved search. Go to the Kibana Alerts and Actions interface and create a new alert. Choose the saved search you created in step 2 as the basis for the alert. Configure the alert to trigger when a certain threshold is met. For example, you can configure the alert to trigger when there are more than 5 failed login attempts within a 5-minute window. Configure the alert to send a notification, such as an email or Slack message, when it triggers. Test the alert to ensure that it is working as expected. Once the alert is configured, it will automatically trigger when it detects a Host Hack Attempt event, such as a failed login attempt. This can help organizations detect and respond to security threats efficiently and effectively. It is important to regularly review and update your alerts to ensure they are detecting the most relevant and important security events. Conclusion Using ELK to detect host hack attempts is an effective approach to enhance the security posture of an organization. ELK provides a powerful combination of log collection, parsing, storage, analysis, and alerting capabilities, which enable organizations to detect and respond to host hack attempts in real-time. By monitoring system logs and network traffic, and using advanced search queries and alerting mechanisms, ELK can help organizations detect a wide range of host hack attempts, including failed login attempts, suspicious network traffic, file system changes, and suspicious process activity. Implementing a robust host hack attempt detection strategy using ELK requires careful planning, configuration, and testing. However, with the right expertise and tools, organizations can create a comprehensive security monitoring system that provides real-time visibility into their network, improves incident response times, and helps prevent security breaches before they occur.
There is a common problem most backend developers face at least once in their careers: where should we store our secrets? It appears to be simple enough, we have a lot of services focusing on this very issue, we just need to pick one and get on the next task. Sounds easy, but how can we pick the right solution for our needs? We should evaluate our options to see more clearly. The Test For the demonstration, we can take a simple Spring Boot application as an example. This will be perfect for us because that is one of the most popular technology choices on the backend today. In our example, we will assume we need to use a MySQL database over JDBC; therefore, our secrets will be the connection URL, driver class name, username, and password. This is only a proof of concept, any dependency would do as long as it uses secrets. We can easily generate such a project using Spring Initializr. We will get the DataSource auto configured and then create a bean that will do the connection test. The test can look like this: Java @Component public class MySqlConnectionCheck { private final DataSource dataSource; @Autowired public MySqlConnectionCheck(DataSource dataSource) { this.dataSource = dataSource; } public void verifyConnectivity() throws SQLException { try (final Connection connection = dataSource.getConnection()) { query(connection); } } private void query(Connection connection) throws SQLException { final String sql = "SELECT CONCAT(@@version_comment, ' - ', VERSION()) FROM DUAL"; try (final ResultSet resultSet = connection.prepareStatement(sql).executeQuery()) { resultSet.next(); final String value = resultSet.getString(1); //write something that will be visible on the Gradle output System.err.println(value); } } } This class will establish a connection to MySQL, and make sure we are, in fact, using MySQL as it will print the MySQL version comment and version. This way we would notice our mistake even if an auto configured H2 instance was used by the application. Furthermore, if we generate a random password for our MySQL Docker container, we can make sure we are using the instance we wanted, validating the whole configuration worked properly. Back to the problem, shall we? Storing Secrets The Easy Way The most trivial option is to store the secrets together with the code, either hard-coded or as a configuration property, using some profiles to be able to use separate environments (dev/test/staging/prod). As simple as it is, this is a horrible idea as many popular sites had to learn the hard way over the years. These “secrets” are anything but a secret. As soon as someone gets access to a repository, they will have the credentials to the production database. Adding insult to injury, we won’t even know about it! This is the most common cause of data breaches. A good indicator of the seriousness of the situation is to see how common secret scanning offerings got for example on GitHub, GitLab, Bitbucket, or others hosting git repositories. The Right Way Now that we see what the problem is, we can start to look for better options. There is one common thing we will notice in all the solutions we can use: they want us to store our secrets in an external service that will keep them secure. This comes with a lot of benefits these services can provide, such as: Solid access control. Encrypted secrets (and sometimes more, like certificates, keys). Auditable access logs. A way to revoke access/rotate secrets in case of a suspected breach. Natural separation of environments as they are part of the stack (one secrets manager per env). Sounds great, did we solve everything? Well, it is not that simple. We have some new questions we need to answer first: Who will host and maintain these? Where should we put the secrets we need for authentication when we want to access the secrets manager? How will we run our code locally on the developer laptops? How will we run our tests on CI? Will it cost anything? These are not trivial, and their answers depend very much on the solution we want to use. Let us review them one by one in the next section. Examples of Secrets Managers In all cases below, we will introduce the secrets manager as a new component of our stack, so if we had an application and a database, it would look like the following diagram. HashiCorp Vault If we go for the popular open-source option, HashiCorp Vault, then we can either self-host, or use their managed service, HCP Vault. Depending on the variant we select, we may or may not have some maintenance effort already, but it answers the first question. Answering the rest should be easy as well. Regarding the authentication piece, we can use, for example, the AppRole Auth Method using environment variables providing the necessary credentials to our application instances in each environment. Regarding the local and CI execution, we can simply configure and run a vault instance in dev server mode on the machine where the app should run and pass the necessary credentials using environment variables similarly to the live app instances. As these are local vaults, providing access to throw-away dev databases, we should not worry too much about their security as we should avoid storing meaningful data in them. To avoid spending a lot of effort on maintaining these local/CI vault instances, it can be a clever idea to store their contents in a central location, and let each developer update their vault using a single command every now and then. Regarding the cost, it depends on a few things. If you can go with the self-hosted open-source option, you should worry only about the VM cost (and the time spent on maintenance); otherwise, you might need to figure out how you can optimize the license/support cost. Cloud-Based Solutions If we are hosting our services using the services of one of the three big cloud providers, we have even more options. AWS, Azure, and Google Cloud are all offering a managed service for secrets managers. Probably because of the nature of the problem, AWS Secrets Manager, Azure Key Vault, and Google Cloud Secret Manager share many similarities. Please see a list below for examples: Stores versioned secrets. Logs access to the service and its contents. Uses solid authentication and authorization features. Well integrated with other managed services of the same provider Provides an SDK for developers of some popular languages At the same time, we should keep in mind that these are still hugely different services. Some of the obvious differences are the API they are using for communication, and the additional features they provide. For example, Azure Key Vault can store secrets, keys, and certificates, while AWS and GCP provide separate managed services for these additional features. Thinking about the questions we wanted to answer, they can answer the first two questions the same way. All of them are managed services, and the managed identity solution of the cloud provider they belong to is the most convenient, secure way to access them. Thanks to this, we do not need to bother storing secrets/tokens in our application configuration, just the URL of the secrets manager, which is not considered to be a secret. Regarding the cost, AWS and GCP can charge by the number of secrets and number of API calls. On the other hand, Azure only charges for the latter. In general, they are very reasonably priced, and we can sleep better at night knowing our security posture is a bit better. Trouble starts when we try to answer the remaining two questions dealing with the local and CI use-cases. All three solutions can be accessed from the outside world (given the proper network configuration), but simply punching holes on a firewall and sharing the same secrets manager credentials is not an ideal solution. There are situations when doing so is simply not practical, such as the following cases: Our team is scattered around the globe in the home office, and we would not be able to use strong IP restrictions, or we would need constant VPN connection just to build/test the code. Needing internet connection for tests is bad enough. But, using VPN constantly while at work can put additional stress on the infrastructure and team at the same time. When our CI instances are spawning with random IPs from an unknown range, we cannot set proper IP restrictions. A similar case to the previous. We cannot trust the whole team with the secrets of the shared secrets manager. For example, in the case of open-source projects, we cannot run around and share a secrets manager instance with the rest of the world. We need to change the contents of the secrets manager during the tests. When this happens, we are risking isolation problems between each developer and CI instance. We cannot launch a different secrets manager instance for each person and process (or test case) as that would not be very scalable. We do not want to pay extra for the additional secrets managers used in these cases. Can We Fake It Locally? Usually, this would be the moment when I start to search for a suitable test double and formulate plans about using that instead of the real service locally and on CI. What do we expect from such a test double? Behave like the real service would include in exceptional situations. Be actively maintained to reduce the risk of lagging behind in case of API version changes in the real service. Have a way to initialize the content of the secrets manager double on start-up to not need additional code in the application. Allow us to synchronize the secret values between the team and CI instances to reduce maintenance cost. Let us start and throw-away the test double simply, locally and on CI. Do not use a lot of resources. Do not introduce additional dependencies to our application if possible. I know about third-party solutions ticking all the boxes in case of AWS or Azure, while I have failed to locate one for GCP. Solving the Local Use Case for Each Secrets Manager in Practice It is finally time for us to roll up our sleeves and get our hands dirty. How should we modify our test project to be able to use our secrets manager integrations locally? Let us see for each of them: HashiCorp Vault Since we can run the real thing locally, getting a test double is pointless. We can simply integrate vault using the Spring Vault module by adding a property source: Java @Component("SecretPropertySource") @VaultPropertySource(value = "secret/datasource", propertyNamePrefix = "spring.datasource.") public class SecretPropertySource { private String url; private String username; private String password; private String driverClassName; // ... getters and setters ... } As well as a configuration for the “dev” profile: Java @Configuration @Profile("dev") public class DevClientConfig extends AbstractVaultConfiguration { @Override public VaultEndpoint vaultEndpoint() { final String uri = getEnvironment().getRequiredProperty("app.secrets.url"); return VaultEndpoint.from(URI.create(uri)); } @Override public ClientAuthentication clientAuthentication() { final String token = getEnvironment().getRequiredProperty("app.secrets.token"); return new TokenAuthentication(token); } @Override public VaultTemplate vaultTemplate() { final VaultTemplate vaultTemplate = super.vaultTemplate(); final SecretPropertySource datasourceProperties = new SecretPropertySource(); datasourceProperties.setUrl("jdbc:mysql://localhost:15306/"); datasourceProperties.setDriverClassName("com.mysql.cj.jdbc.Driver"); datasourceProperties.setUsername("root"); datasourceProperties.setPassword("16276ec1-a682-4022-b859-38797969abc6"); vaultTemplate.write("secret/datasource", datasourceProperties); return vaultTemplate; } } We need to be careful, as each bean—depending on the fetched secret values (or the DataSource)—must be marked with @DependsOn("SecretPropertySource") to make sure it will not be populated earlier during start-up while the vault backend PropertySource is not registered. As for the reason we used a “dev” specific profile, it was necessary because of two things: The additional initialization of the vault contents on start-up. The simplified authentication as we are using a simple token instead of the aforementioned AppRole. Performing the initialization here solves the worries about the maintenance of the vault contents as the code takes care of it, and we did not need any additional dependencies either. Of course, it would have been even better if we used some Docker magic to add those values without ever needing to touch Java. This might be an improvement for later. Speaking of Docker, the Docker Compose file is simple as seen below: YAML version: "3" services: vault: container_name: self-hosted-vault-example image: vault ports: - '18201:18201' restart: always cap_add: - IPC_LOCK entrypoint: vault server -dev-kv-v1 -config=/vault/config/vault.hcl volumes: - config-import:/vault/config:ro environment: VAULT_DEV_ROOT_TOKEN_ID: 00000000-0000-0000-0000-000000000000 VAULT_TOKEN: 00000000-0000-0000-0000-000000000000 # ... MySQL config ... volumes: config-import: driver: local driver_opts: type: "none" o: "bind" device: "vault" The key points to remember are the dev mode in the entry point, the volume config that will allow us to add the configuration file, and the environment variables baking in the dummy credentials we will use in the application. As for the configuration, we need to set in-memory mode and configure a HTTP endpoint without TLS: disable_mlock = true storage "inmem" {} listener "tcp" { address = "0.0.0.0:18201" tls_disable = 1 } ui = true max_lease_ttl = "7200h" default_lease_ttl = "7200h" api_addr = "http://127.0.0.1:18201" The complexity of the application might need some changes in the vault configuration or the Docker Compose content. However, for this simple example, we should be fine. Running the project, should produce the expected output: MySQL Community Server - GPL - 8.0.32 We are done with configuring vault for local use. Setting it up for tests should be even more simple using the things we have learned here. Also, we can simplify some of the steps there if we decide to use the relevant Testcontainers module. Google Cloud Secret Manager As there is no readily available test double for Google Cloud Secret Manager, we need to make a trade-off. We can decide what we would like to choose from the following three options: We can fall back to the easy option in case of the local/CI case, disabling the logic that will fetch the secrets for us in any real environment. In this case, we will not know whether the integration works until we deploy the application somewhere. We can decide to use some shared Secret Manager instances, or even let every developer create one for themselves. This can solve the problem locally, but it is inconvenient compared to the solution we wanted, and we would need to avoid running our CI tests in parallel and clean up perfectly in case the content of the Secret Manager must change on CI. We can try mocking/stubbing the necessary endpoints of the Secret Manager ourselves. WireMock can be a good start for the HTTP API, or we can even start from nothing. It is a worthy endeavor for sure, but will take a lot of time to do it well. Also, if we do this, we must consider the ongoing maintenance effort. As the decision will require quite different solutions for each, there is not much we can solve in general. AWS Secrets Manager Things are better in case of AWS, where LocalStack is a tried-and-true test double with many features. Chances are that if you are using other AWS managed services in your application, you will be using LocalStack already, making this even more appealing. Let us make some changes to our demo application to demonstrate how simple it is to implement the AWS Secrets Manager integration as well as using LocalStack locally. Fetching the Secrets First, we need a class that will know the names of the secrets in the Secrets Manager: Java @Configuration @ConfigurationProperties(prefix = "app.secrets.key.db") public class SecretAccessProperties { private String url; private String username; private String password; private String driver; // ... getters and setters ... } This will read the configuration and let us conveniently access the names of each secret by a simple method call. Next, we need to implement a class that will handle communication with the Secrets Manager: Java @Component("SecretPropertySource") public class SecretPropertySource extends EnumerablePropertySource<Map<String, String>> { private final AWSSecretsManager client; private final Map<String, String> mapping; private final Map<String, String> cache; @Autowired public SecretPropertySource(SecretAccessProperties properties, final AWSSecretsManager client, final ConfigurableEnvironment environment) { super("aws-secrets"); this.client = client; mapping = Map.of( "spring.datasource.driver-class-name", properties.getDriver(), "spring.datasource.url", properties.getUrl(), "spring.datasource.username", properties.getUsername(), "spring.datasource.password", properties.getPassword() ); environment.getPropertySources().addFirst(this); cache = new ConcurrentHashMap<>(); } @Override public String[] getPropertyNames() { return mapping.keySet() .toArray(new String[0]); } @Override public String getProperty(String property) { if (!Arrays.asList(getPropertyNames()).contains(property)) { return null; } final String key = mapping.get(property); //not using computeIfAbsent to avoid locking map while the value is resolved if (!cache.containsKey(key)) { cache.put(key, client .getSecretValue(new GetSecretValueRequest().withSecretId(key)) .getSecretString()); } return cache.get(key); } } This PropertySource implementation will know how each secret name can be translated to Spring Boot configuration properties used for the DataSource configuration, self-register as the first property source, and cache the result whenever a known property is fetched. We need to use the @DependsOn annotation same as in case of the vault example to make sure the properties are fetched in time. As we need to use basic authentication with LocalStack, we need to implement one more class, which will only run in the “dev” profile: Java @Configuration @Profile("dev") public class DevClientConfig { @Value("${app.secrets.url}") private String managerUrl; @Value("${app.secrets.accessKey}") private String managerAccessKey; @Value("${app.secrets.secretKey}") private String managerSecretKey; @Bean public AWSSecretsManager secretClient() { final EndpointConfiguration endpointConfiguration = new EndpointConfiguration(managerUrl, Regions.DEFAULT_REGION.getName()); final BasicAWSCredentials credentials = new BasicAWSCredentials(managerAccessKey, managerSecretKey); return AWSSecretsManagerClientBuilder.standard() .withEndpointConfiguration(endpointConfiguration) .withCredentials(new AWSStaticCredentialsProvider(credentials)) .build(); } } Our only goal with this service is to set up a suitable AWSSecretsManager bean just for local use. Setting Up the Test Double With the coding done, we need to make sure LocalStack will be started using Docker Compose whenever we start our Spring Boot app locally and stop it when we are done. Starting with the Docker Compose part, we need it to start LocalStack and make sure to use the built-in mechanism for running an initialization script when the container starts using the approach shared here. To do so, we need a script that can add the secrets: Shell #!/bin/bash echo "########### Creating profile ###########" aws configure set aws_access_key_id default_access_key --profile=localstack aws configure set aws_secret_access_key default_secret_key --profile=localstack aws configure set region us-west-2 --profile=localstack echo "########### Listing profile ###########" aws configure list --profile=localstack echo "########### Creating secrets ###########" aws secretsmanager create-secret --endpoint-url=http://localhost:4566 --name database-connection-url --secret-string "jdbc:mysql://localhost:13306/" --profile=localstack || echo "ERROR" aws secretsmanager create-secret --endpoint-url=http://localhost:4566 --name database-driver --secret-string "com.mysql.cj.jdbc.Driver" --profile=localstack || echo "ERROR" aws secretsmanager create-secret --endpoint-url=http://localhost:4566 --name database-username --secret-string "root" --profile=localstack || echo "ERROR" aws secretsmanager create-secret --endpoint-url=http://localhost:4566 --name database-password --secret-string "e8ce8764-dad6-41de-a2fc-ef905bda44fb" --profile=localstack || echo "ERROR" echo "########### Secrets created ###########" This will configure the bundled AWS CLI inside the container and perform the necessary HTTP calls to port 4566 where the container listens. To let LocalStack use our script, we will need to start our container with a volume attached. We can do so using the following Docker Compose configuration: YAML version: "3" services: localstack: container_name: aws-example-localstack image: localstack/localstack:latest ports: - "14566:4566" environment: LAMBDA_DOCKER_NETWORK: 'my-local-aws-network' LAMBDA_REMOTE_DOCKER: 0 SERVICES: 'secretsmanager' DEFAULT_REGION: 'us-west-2' volumes: - secrets-import:/docker-entrypoint-initaws.d:ro # ... MySQL config ... volumes: secrets-import: driver: local driver_opts: type: "none" o: "bind" device: "localstack" This will set up the volume, start LocalStack with the “secretsmanager” feature active, and allow us to map port 4566 from the container to port 14566 on the host so that our AWSSecretsManager can access it using the following configuration: Properties files app.secrets.url=http://localhost:14566 app.secrets.accessKey=none app.secrets.secretKey=none If we run the project, we will see the expected output: MySQL Community Server - GPL - 8.0.32 Well done, we have successfully configured our local environment. We can easily replicate these steps for the tests as well. We can even create multiple throw-away containers from our tests for example using Testcontainers. Azure Key Vault Implementing the Azure Key Vault solution will look like a cheap copy-paste job after the AWS Secrets Manager example we have just implemented above. Fetching the Secrets We have the same SecretAccessProperties class for the same reason. The only meaningful difference in SecretPropertySource is the fact that we are using the Azure SDK. The changed method will be this: Java @Override public String getProperty(String property) { if (!Arrays.asList(getPropertyNames()).contains(property)) { return null; } final String key = mapping.get(property); //not using computeIfAbsent to avoid locking map while the value is resolved if (!cache.containsKey(key)) { cache.put(key, client.getSecret(key).getValue()); } return cache.get(key); } The only missing piece is the “dev” specific client configuration that will create a dumb token and an Azure Key Vault SecretClient for us: Java @Configuration @Profile("dev") public class DevClientConfig { @Value("${app.secrets.url}") private String vaultUrl; @Value("${app.secrets.user}") private String vaultUser; @Value("${app.secrets.pass}") private String vaultPass; @Bean public SecretClient secretClient() { return new SecretClientBuilder() .credential(new BasicAuthenticationCredential(vaultUser, vaultPass)) .vaultUrl(vaultUrl) .disableChallengeResourceVerification() .buildClient(); } } With this, the Java side changes are completed, we can add the missing configuration and the application is ready: Properties files app.secrets.url=https://localhost:10443 app.secrets.user=dummy app.secrets.pass=dummy The file contents are self-explanatory, we have some dummy credentials for the simulated authentication and a URL for accessing the vault. Setting Up the Test Double Although setting up the test double will be like the LocalStack solution we implemented above, it will not be the same. We will use Lowkey Vault, a fake, that implements the API endpoints we need and more. As Lowkey Vault provides a way for us to import the vault contents using an attached volume, we can start by creating an import file containing the properties we will need: { "vaults": [ { "attributes": { "baseUri": "https://{{host}:{{port}", "recoveryLevel": "Recoverable+Purgeable", "recoverableDays": 90, "created": {{now 0}, "deleted": null }, "keys": { }, "secrets": { "database-connection-url": { "versions": [ { "vaultBaseUri": "https://{{host}:{{port}", "entityId": "database-connection-url", "entityVersion": "00000000000000000000000000000001", "attributes": { "enabled": true, "created": {{now 0}, "updated": {{now 0}, "recoveryLevel": "Recoverable+Purgeable", "recoverableDays": 90 }, "tags": {}, "managed": false, "value": "jdbc:mysql://localhost:23306/", "contentType": "text/plain" } ] }, "database-username": { "versions": [ { "vaultBaseUri": "https://{{host}:{{port}", "entityId": "database-username", "entityVersion": "00000000000000000000000000000001", "attributes": { "enabled": true, "created": {{now 0}, "updated": {{now 0}, "recoveryLevel": "Recoverable+Purgeable", "recoverableDays": 90 }, "tags": {}, "managed": false, "value": "root", "contentType": "text/plain" } ] }, "database-password": { "versions": [ { "vaultBaseUri": "https://{{host}:{{port}", "entityId": "database-password", "entityVersion": "00000000000000000000000000000001", "attributes": { "enabled": true, "created": {{now 0}, "updated": {{now 0}, "recoveryLevel": "Recoverable+Purgeable", "recoverableDays": 90 }, "tags": {}, "managed": false, "value": "5b8538b6-2bf1-4d38-94f0-308d4fbb757b", "contentType": "text/plain" } ] }, "database-driver": { "versions": [ { "vaultBaseUri": "https://{{host}:{{port}", "entityId": "database-driver", "entityVersion": "00000000000000000000000000000001", "attributes": { "enabled": true, "created": {{now 0}, "updated": {{now 0}, "recoveryLevel": "Recoverable+Purgeable", "recoverableDays": 90 }, "tags": {}, "managed": false, "value": "com.mysql.cj.jdbc.Driver", "contentType": "text/plain" } ] } } } ] } This is a Handlebars template that would allow us to use placeholders for the host name, port, and the created/updated/etc., timestamp fields. We must use the {{port} placeholder as we want to make sure we can use any port when we start our container, but the rest of the placeholders are optional, we could have just written a literal there. See the quick start documentation for more information. Starting the container has a similar complexity as in case of the AWS example: YAML version: "3" services: lowkey-vault: container_name: akv-example-lowkey-vault image: nagyesta/lowkey-vault:1.18.0 ports: - "10443:10443" volumes: - vault-import:/import/:ro environment: LOWKEY_ARGS: > --server.port=10443 --LOWKEY_VAULT_NAMES=- --LOWKEY_IMPORT_LOCATION=/import/keyvault.json.hbs # ... MySQL config ... volumes: vault-import: driver: local driver_opts: type: "none" o: "bind" device: "lowkey-vault/import" We need to notice almost the same things as before, the port number is set, the Handlebars template will use the server.port parameter and localhost by default, so the import should work once we have attached the volume using the same approach as before. The only remaining step we need to solve is configuring our application to trust the self-signed certificate of the test double, which is used for providing an HTTPS connection. This can be done by using the PKCS#12 store from the Lowkey Vault repository and telling Java that it should be trusted: Groovy bootRun { systemProperty("javax.net.ssl.trustStore", file("${projectDir}/local/local-certs.p12")) systemProperty("javax.net.ssl.trustStorePassword", "changeit") systemProperty("spring.profiles.active", "dev") dependsOn tasks.composeUp finalizedBy tasks.composeDown } Running the project will log the expected string as before: MySQL Community Server - GPL - 8.0.32 Congratulations, we can run our app without the real Azure Key Vault. Same as before, we can use Testcontainers for our test, but, in this case, the Lowkey Vault module is a third-party from the Lowkey Vault project home, so it is not in the list provided by the Testcontainers project. Summary We have established that keeping secrets in the repository defeats the purpose. Then, we have seen multiple solution options for the problem we have identified in the beginning, and can select the best secrets manager depending on our context. Also, we can tackle the local and CI use cases using the examples shown above. The full example projects can be found on GitHub here.
A Software Bill of Materials (SBOM) is getting more and more important in the software supply chain. In this blog, you will learn what an SBOM is and how to build the SBOM in an automated way. Enjoy! 1. Introduction An SBOM is a list of software components that makes up a software product. This way, it becomes transparent which software libraries, components, etc., and their versions are used in the software product. As a consequence, you will be able to react more adequately when a security vulnerability is reported. You only need to check the SBOMs for the vulnerable library, and you will know immediately which applications are impacted by the vulnerability. The SBOM of a library or application you want to use can also help you in your decision-making. It will become more common ground that software suppliers will be forced to deliver an up-to-date SBOM with each software delivery. Based on this information, you can make a risk assessment of whether you want to use the library or application. When you are a software supplier, you need to ensure that you deliver an SBOM with each software release. This actually means that you need to create the SBOM in an automated way, preferably in your build pipeline. As written before, the SBOM can help you to check whether a library used in your application contains security vulnerabilities. With the proper tooling, this check can be done in an automated way in your build pipeline. When security vulnerabilities are found, you can fail the build pipeline. One of these tools is grype, which can take an SBOM as input and check whether any components are used with known security vulnerabilities. In a previous post, it is explained how grype can be used. In the post, a Docker image is input to grype, but it is even better to create an SBOM first and then provide it to grype. How to create the SBOM will be explained in this post. When you start reading about SBOMs, you will notice that two standards are commonly used: CycloneDX: an open-source project originated within the OWASP community; SPDX (The Software Package Data Exchange): an international open standard format, also open source and hosted by the Linux foundation. So, which standard to use? This is a difficult question to answer. Generally, it is stated that both standards will continue to exist next to each other, and tools are advised to support both standards. SPDX is initially set up for license management, whereas CycloneDX had its primary focus on security. Reading several resources, the preferred format is CycloneDX when your focus is set on security. Interesting reads are SBOM formats SPDX and CycloneDX compared and the publication Using the Software Bill of Materials for Enhancing Cybersecurity from the National Cyber Security Centre of the Ministry of Justice and Security of the Netherlands. The latter is a must-read. In the remainder of this blog, you will learn how to use syft for building an SBOM. Syft is also a product of Anchore, just like grype is, and therefore integrates well with grype, the vulnerability scanning tool. Syft supports many ecosystems and has several export formats. It definitely supports CycloneDX and SPDX. CycloneDX also has tools for building SBOMs, but Syft is one tool that supports many ecosystems, which is an advantage compared to multiple tools. Sources being used in this post are available at GitHub. 2. Prerequisites The prerequisites needed for this blog are: Basic Linux knowledge; Basic Java knowledge; Basic JavaScript knowledge; Basic Spring Boot knowledge. 3. Application Under Test Before continuing, you need an application to build the SBOM. This is a basic application that consists of a Spring Boot backend and a Vue.js frontend. The application can be built with Maven and contains two Maven modules, one for the backend and one for the front end. More information about the setup can be read in a previous post. It is important, however, to build the application first. This can be done with the following command: Shell $ mvn clean verify 4. Installation Installation of syft can be done by executing the following script: Shell $ curl -sSfL https://raw.githubusercontent.com/anchore/syft/main/install.sh | sudo sh -s -- -b /usr/local/bin Verify the installation by executing the following command: Shell $ syft --version syft 0.64.0 5. Build Backend SBOM Navigate to the backend directory and execute the following command: Shell $ syft dir:. --exclude ./**/sbom.*.json --output cyclonedx-json=sbom.cyclonedx.build-complete-dir.json The parameters will do the following: dir:.: Scan the entire directory in order to find dependencies; –exclude: Exclude already present SBOM files because you want to generate the SBOM file every time anew based on the current state of the repository; –output: Here, you define the output format to use, and you define the file name of the SBOM file. The SBOM file sbom.cyclonedx.build-complete-dir.json is created in the backend directory. Take a closer look at the SBOM format. JSON { "bomFormat": "CycloneDX", "specVersion": "1.4", "serialNumber": "urn:uuid:afbe7b48-b376-40fb-a0d4-6a16fda38a0f", "version": 1, "metadata": { "timestamp": "2023-01-14T16:35:35+01:00", "tools": [ { "vendor": "anchore", "name": "syft", "version": "0.64.0" } ], "component": { "bom-ref": "af63bd4c8601b7f1", "type": "file", "name": "." } }, "components": [ ... ] } The top part consists of metadata: the format of the SBOM, versions used, which tool is being used, etc. The component part consists of a list of all the components syft has found. The complete specification of CycloneDX can be found here. The component list is the following and corresponds to the list of libraries that can be found in the target/backend-0.0.1-SNAPSHOT.jar file. The libraries are located in the directory /BOOT-INF/lib/ in the jar file (the jar file is just a zip file and can be opened with any archive tool). Plain Text backend jackson-annotations jackson-core jackson-databind jackson-datatype-jdk8 jackson-datatype-jsr310 jackson-module-parameter-names jakarta.annotation-api jul-to-slf4j log4j-api log4j-to-slf4j logback-classic logback-core micrometer-commons micrometer-observation slf4j-api snakeyaml spring-aop spring-beans spring-boot spring-boot-autoconfigure spring-boot-jarmode-layertools spring-boot-starter-test spring-boot-starter-web spring-context spring-core spring-expression spring-jcl spring-web spring-webmvc tomcat-embed-core tomcat-embed-el tomcat-embed-websocket Now take a closer look at the jackson-annotations component in the SBOM file. In the properties section, you can see that this component has a property syft:package:foundBy with the value java-cataloger. This means that this component was found in the jar file. JSON { "bom-ref": "pkg:maven/com.fasterxml.jackson.core/jackson-annotations@2.14.1?package-id=9cdc3a1e17ebbb68", "type": "library", "group": "com.fasterxml.jackson.core", "name": "jackson-annotations", "version": "2.14.1", "cpe": "cpe:2.3:a:jackson-annotations:jackson-annotations:2.14.1:*:*:*:*:*:*:*", "purl": "pkg:maven/com.fasterxml.jackson.core/jackson-annotations@2.14.1", "externalReferences": [ { "url": "", "hashes": [ { "alg": "SHA-1", "content": "2a6ad504d591a7903ffdec76b5b7252819a2d162" } ], "type": "build-meta" } ], "properties": [ { "name": "syft:package:foundBy", "value": "java-cataloger" }, { "name": "syft:package:language", "value": "java" }, { "name": "syft:package:metadataType", "value": "JavaMetadata" }, { "name": "syft:package:type", "value": "java-archive" }, ... ] } When you take a look at component spring-boot-starter-web, it mentions that this component was found by java-pom-cataloger. This means that this component was found in the pom file. This is quite interesting because this would mean that syft cannot find transitive dependencies based on the sources only. Execute the following command where the target directory is excluded from the analysis. Shell $ syft dir:. --exclude ./**/sbom.*.json --exclude ./**/target --output cyclonedx-json=sbom.cyclonedx.build-sources.json The result can be found in the file sbom.cyclonedx.build-sources.json and the previously made assumption seems to be right. Only the spring-boot-starter-web and spring-boot-starter-test dependencies are found. This is, after all, not a big issue, but you have to be aware of this. 6. Build Frontend SBOM Navigate to the frontend directory and execute the following command: Shell $ syft dir:. --exclude ./**/sbom.*.json --output cyclonedx-json=sbom.cyclonedx.build-complete-dir.json This analysis takes a bit longer than the backend analysis, but after a few seconds, the sbom.cyclonedx.build-complete-dir.json file is created. Again, similar information can be found in the SBOM. The information is now available from the javascript-lock-cataloger. This means that it originates from the package-lock.json file. Another difference is that the components also contain license information. JSON "components": [ { "bom-ref": "pkg:npm/%40babel/parser@7.20.7?package-id=ca6a526d8a318088", "type": "library", "name": "@babel/parser", "version": "7.20.7", "licenses": [ { "license": { "id": "MIT" } } ], ... License information is included and can be used to check regarding allowed company policies. This information is, however, not yet available for Java packages. 7. Conclusion SBOMs will become more and more important in the software development lifecycle. More and more customers will demand an SBOM, and therefore it is important to automatically generate the SBOM. Syft can help you with that. Besides that, the SBOM can be fed to grype in order to perform a security vulnerability analysis.
Though the Internet of Things (IoT) has redefined our lives and brought a lot of benefits, it has a large attack surface area and is not safe until it is secure. IoT devices are an easy target for cybercriminals and hackers if not properly secured. You may have serious problems with financial and confidential data being invaded, stolen, or encrypted. It is difficult to spot and discuss risks for organizations, let alone build a comprehensive methodology for dealing with them, without practical knowledge of what IoT security is and testing it. Realizing the security threats and how to avoid them is the first step, as Internet of Things solutions require significantly more testing than before. Integrated security is frequently lacking when it comes to introducing new features and products to the market. What Is IoT Security Testing? IoT security testing is the practice of evaluating cloud-connected devices and networks to reveal security flaws and prevent devices from being hacked and compromised by a third party. The biggest IoT security risks and challenges can be addressed through a focused approach with the most critical IoT vulnerabilities. Most Critical IoT Security Vulnerabilities There are typical issues in security analysis faced by organizations that are missed even by experienced companies. Adequate testing Internet of Things (IoT) security in networks and devices is required, as any hack into the system can bring a business to a standstill, leading to a loss in revenue and customer loyalty. The top ten common vulnerabilities are as follows: 1. Weak Easy-to-Guess Passwords Absurdly simple and short passwords that put personal data at risk are among the primary IoT security risks and vulnerabilities for most cloud-connected devices and their owners. Hackers can co-opt multiple devices with a single guessable password, jeopardizing the entire network. 2. Insecure Ecosystem Interfaces Insufficient encryption and verification of the user’s identity or access rights in the ecosystem architecture, which is software, hardware, network, and interfaces outside of the device, enable the devices and associated components to get infected by malware. Any element in the broad network of connected technologies is a potential source of risk. 3. Insecure Network Services The services running on the device should be given special attention, particularly those that are open to the Internet and have a high risk of illegal remote control. Do not keep ports open, update protocols, and ban any unusual traffic. 4. Outdated Components Outdated software elements or frameworks make a device unprotected from cyberattacks. They enable third parties to interfere with the performance of the gadgets, operating them remotely or expanding the attack surface for the organization. 5. Insecure Data Transfer/Storage The more devices are connected to the network, the higher the level of data storage/exchange should be. A lack of secure encoding in sensitive data, whether it is at rest or transferred, can be a failure for the whole system. 6. Bad Device Management Bad device management happens because of a poor perception of and visibility into the network. Organizations have a bunch of different devices that they do not even know about, which are easy entry points for attackers. IoT developers are simply unprepared in terms of proper planning, implementation, and management tools. 7. Poor Secure Update Mechanism The ability to securely update the software, which is the core of any IoT device, reduces the chances of it being compromised. The gadget becomes vulnerable every time cybercriminals discover a weak point in security. Similarly, if it is not fixed with regular updates, or if there are no regular notifications of security-related changes, it can become compromised over time. 8. Inadequate Privacy Protection Personal information is gathered and stored in larger amounts on IoT devices than on smartphones. In case of improper access, there is always a threat of your information being exposed. It is a major privacy concern because most Internet of Things technologies are somehow related to monitoring and controlling gadgets at home, which can have serious consequences later. 9. Poor Physical Hardening Physical hardening is one of the major aspects of high security IoT devices since they are a cloud computing technology that operates without human intervention. Many of them are intended to be installed in public spaces (instead of private homes). As a result, they are created in a basic manner, with no additional level of physical security. 10. Insecure Default Settings Some IoT devices come with default settings that cannot be modified, or there is a lack of alternatives for operators when it comes to security adjustments. The initial configuration should be modifiable. Default settings that are invariant across multiple devices are insecure. Once guessed, they are used to hack into other devices. How To Protect IoT Systems and Devices Easy-to-use gadgets with little regard for data privacy make IoT security on smart devices tricky. The software interfaces are unsafe, and data storage/transfer is not sufficiently encrypted. Here are the steps to keep networks and systems safe and secure: Introduce IoT security during the design phase: IoT security strategy has the greatest value if it is introduced from the very beginning, the design stage. Most concerns and threats that have risks to an Internet of Things solution may be avoided by identifying them during preparation and planning. Network security: Since networks pose the risk of any IoT device being remotely controlled, they play a critical role in cyber protection strategy. The network stability is ensured by port security, animal ware, firewall, and banned IP addresses that are not usually used by a user. API security: Sophisticated businesses and websites use APIs to connect services, transfer data, and integrate various types of information in one place, making them a target for hackers. A hacked API can result in the disclosure of confidential information. That is why only approved apps and devices should be permitted to send requests and responses with APIs. Segmentation: It is important to follow segmentation for a corporate network if multiple IoT devices are connecting directly to the web. Each of the devices should use its small local network (segment) with limited access to the main network. Security gateways: Serve as an additional level in security IoT infrastructure before sending data produced by a device out to the Internet. They help track and analyze incoming and outgoing traffic, ensuring someone else cannot directly reach the gadget. Software updates: Users should be able to set changes to software and devices by updating them over a network connection or through automation. Improved software means incorporating new features as well as assisting in identifying and eliminating security defects in the early stages. Integrating teams: Many people are involved in the IoT development process. They are equally responsible for ensuring the product’s security throughout the full lifecycle. It is preferable to have IoT developers get together with security experts to share guidance and necessary security controls right from the design stage. Our team consists of cross-functional experts who are involved from the beginning to the end of the project. We support clients with developing digital strategies based on the requirements analysis, planning an IoT solution, and performing IoT security testing services so they can launch a glitch-free Internet of Things product. Conclusion To create trustworthy devices and protect them from cyber threats, you have to maintain a defensive and proactive security strategy throughout the entire development cycle. I hope you take away some helpful tips and tricks that will help you test your IoT security. If you have any questions, feel free to comment below.
IAM stands for "Identity and Access Management." IAM provides answers to the fundamental question in DevOps: "Who can access what?" The roots of IAM go back to the early days of computing, where users of UNIX systems needed a username and password to access their accounts and files. As systems got more complex, grew in number, and larger pools of users needed access, identity management solutions like Lightweight Directory Access Protocol, LDAP, became increasingly popular, where a central team could manage access for multiple departments and roles. The revolution of DevOps added a new layer of complexity to access management; non-human entities also needed access to data and systems. These non-humans included both applications on the same platform as well as third-party systems, making things even more complex. While it is commonly associated with AWS and its AWS IAM service, IAM is not limited to its platform. All cloud providers, such as Google Cloud and Azure DevOps, offer IAM solutions that allow users to access resources and systems. For the rest of this article, we will look at the generic best practices that have evolved over the last decade around each part of the basic question we started with, "Who can access what?": Who: Humans and non-human entities (applications and machine workers) Can access: permissions sets What: resources and systems Who: Users in IAM There are two broad groups that we are concerned with in IAM: humans and non-humans. Humans are typically developers, engineers, analysts, or anyone else that needs access to the data and resources in your DevOps environments. IAM services allow you to create specific users for specific roles and assign them any needed permissions. These are not separate accounts but just users under a single account. Non-human entities, also commonly called machine identities, are any system, API, platform, or service that needs to be able to connect and interact with your CI/CD pipeline. IAM systems can grant these entities the access they need and tightly scope it only to allow specific access under the right conditions. We will dive into this kind of access further in the resources and services section. Zero-Trust or Least Privilege Access No matter what kind of user, the principle of least privilege should always be applied. Any new user created or approved should start with no access whatsoever and then only be granted permissions that will let them accomplish their work, but nothing further. This is what we mean by zero trust. By default, most cloud providers use this model so that any new user will start with zero permissions. Only once assigned a role or specific permissions will they be able to access any resources. A Staged Approach to Permissions While we feel everyone should lean into Zero-Trust, it is also important to balance access restriction with real-world business needs. One good way to think about this is to scope access based on the maturity or progress of a project. For example, for early-stage research into a new product or application, giving a user unrestricted access might be necessary to get to a minimum viable product, MVP, effectively. It would be a good idea in that case to create a whole new account dedicated to the project and isolated from your production infrastructure. As the project progresses toward production, additional access restrictions can be applied and fine-tuned, allowing only the needed access to finalize the application. Finally, when launched, permissions can be brought in line with existing company policies and best practices. Identity Providers and Temporary Credentials For human users, the best credentials are short-lived and ones that no human ever sees or knows. This is entirely achievable thanks to identity providers such as AWS IAM Identity Center or Google Cloud Identity. You can also sync a trusted external ID source like Okta Universal Directory, Microsoft Active Domain, or any open-source SAML-based system to get the same result. When leveraging an identity provider, any user authenticates with their identity service and is then issued a short-term token or certificate that is never exposed to the users and, therefore, nearly impossible to leak. There are some additional advantages to this approach, such as: Centralized user stores that are easy to manage Reduced password fatigue from constant password rotation A decreased number of systems to secure overall A centralized ID manager that is simpler to secure and audit Root Users There is a special kind of human user in IAM who control an organization's account on a cloud provider: Root, also known as Super Administrator. These users are ultimately responsible for provisioning access, resources, and billing. These are extremely powerful accounts and should be used with caution. It is a very good idea to avoid using root credentials at all. Instead, create unique users to perform specific jobs. Some providers, like AWS, allow you to block root users from managing or working with some processes, ensuring that these special and powerful accounts stay protected. Since root accounts necessarily require long-lived passwords, it is vital to create complex, high-entropy passwords and protect them. We highly recommend using a password manager like LastPass or 1Password. Combined with multi-factor authentication, MFA. MFA means having something you know, such as a password, combined with something you have, like a Google Authenticator one-time password, OTP, or, better yet, a hardware token. Another approach is to create very long and complex passwords but never store them anywhere after logging in, instead relying on password resets each time access is needed. It is vital for your business to ensure the long-lived credentials for a root user never appear in your code or configuration anywhere. In fact, the best practice is to never use your root user access key and, even better, delete it. While this can sound radical, it has two interesting benefits: it limits vectors by which the account can be compromised (remember, this account has full-administrative privileges!), and it forces the creation of role-based accounts with restricted privileges. Trust is good, but verifying is better. Protect The Credential Recovery Path Make sure you also secure the root credential recovery flow. Unfortunately, there has been a steady increase of phishing attempts recently targeting administrator-level password resets. Attackers know this is a good way to try to steal login credentials. One important element of any password reset strategy is enforcing MFA for any email accounts used for recovery. Another strategy is creating dedicated email accounts for these highly prized and powerful credentials. If malicious actors do not know or can't guess associated email addresses for your root users, then it will make it that much harder for them to launch an attack. Make Sure Your User List is Accurate and Current The easiest user to administer is the one that does not exist. As soon as a user is no longer needed, remove them from the system. Make sure you are auditing users regularly to see if they are still active and behaving as expected. If you ever discover a user you do not recognize accessing your resources, it likely is time to have a conversation with your security team. Can Access — Permissions in IAM The second part of the IAM equation, "who can access what?' is setting permissions. Permissions can be managed per user or per role. Setting permissions for long-lived user accounts might sometimes be necessary, but it means you will need to monitor and manage each of those users' permissions over time. It also means you will need to track what individuals have which permissions to avoid overlap or misconfigurations. The other path you can use for permissions is creating roles. Roles can be assigned any number of permissions, and then you can assign users those roles. This approach makes it much easier to manage permission sets at a larger scale and quickly see who has access to each role. If a new resource is added to your setup, you can quickly add the needed permissions to anyone with a role rather than setting individual user permissions. It makes broadly revoking access to a service that much quicker as well. The AWS EPARC Model While IAM is offered by various vendors, it might be helpful to take a closer look at the model AWS uses for its permission structure, EPARC: Effect — what should happen if permission is allowed Principle — the user or machine worker that is allowed or denied access Action — what will be carried out if access is allowed or denied Resource — the service or data to be accessed Condition — the conditions under which the access can be granted If you can provide and understand all the needed information to satisfy the EPARC model, then you are in a good position to set policy. Use Conditions to Further Restrict Unexpected Access When defining policy, you can use conditions to narrow access rights even further. Conditions are fine-grained controls to define specific circumstances to allow permissions. You can think of these as "but, only if" statements. For example: Grant access to resources, BUT ONLY IF the access request comes from a specific subnet and within a specific IP range Grant access to resources, BUT ONLY IF the access request starts with a specific prefix Allow an AWS Lambda function to be created, BUT ONLY IF using AWS CloudFormation Allow a Google Cloud Function, BUT ONLY IF it will live in a specific VPC While all cloud platforms differ slightly in the implementation specifics, all support implementing conditions. What: Resources and Services in IAM Finally, the last piece of the IAM "who can access what?" puzzle is the resources and services a user can access. In the case that the 'user' is a non-human entity, you can think of it as a 'resource that can access a resource.' Fortunately, if you have handled user authentication and permissions correctly, there is not much you will need to think about for this part. There are basically two types of services; systems on the same platform and third-party services that exist outside the platform. In some rare cases where a team has built its own private cloud, there might not be any 'on-platform' applications at all. Your Data Perimeter One good way to view resources and services is to think about them existing either inside or outside of your 'data perimeter,' which we can define as the boundary between your applications and the rest of the internet. In short, you only ever want trusted identities to be able to access trusted resources from expected locations. If a resource is outside of your data perimeter, then access should be denied. Similarly, if anyone from outside this perimeter tries to gain access to any trusted service, then access should also be denied, and likely alarm bells should be going off. For systems on the same platform, you can generally rely on their provided identity provider service to ensure it is a trusted resource. Even though it is inside your account, it is still a good idea to set conditions to ensure only the expected users can gain access to any service. For third-party applications, there is always the temptation to just quickly embed the access credentials in your configuration… Don't ever do this! This is one of the main paths attackers use to laterally expand during a breach, and sometimes, this is the origin of a breach. Instead, to make them trusted resources, rely on tools like Hashicorp Vault to store any long-lived credentials. Or, even better, integrate with Certificate Authority Services to authenticate automatically via automatically generated and managed certificates. Leverage Tools to Optimize Your IAM Configurations Cloud providers want you to succeed and achieve the best possible security policies. This is the motivation behind tools like AWS IAM Access Analyzer and Google Cloud Policy Analyzer. These are free tools that can help you understand your current settings and fine-tune them.IAM analyzers can show you who has which permissions and, just as importantly, which permissions have not been used. Any unused permissions should be revoked to prevent abuse. They should not be missed since they were not needed for the work to be done. AWS refers to this fine-tuning exercise as 'right-sizing your permissions.'Aside from just analyzing the existing permissions, these tools can also suggest optimal permission sets for a given situation. They can also validate your settings. For example, AWS IAM Access Analyzer claims to offer over 100 validation checks that will show security issues, errors, and general warnings, while providing optimization suggestions. No matter what provider you choose, make sure you look through their documentation for best practices and tools that can help you stay safe. IAM Best Practices Is a Journey For many organizations, the last time IAM was discussed or even thought about was when it was first implemented. If that sounds like you, then you are not alone, but it is likely time to rethink your permissions and answer the question: "who can access what?". While there is no single right answer to that question, all cloud providers agree you should be able to answer that question. As we wrap up this article, we want to sum up our tips on managing IAM: Who: Use Identity Managers to authenticate users Create users for specific tasks with zero permissions by default Never use root accounts for everyday jobs, and delete unused access keys When long-term credentials are in use, ensure they are protected along with their recovery path Enforce MFA everywhere Can Access: Use roles to manage sets of permissions, assigning users roles instead of permissions Think through the EPARC model when assigning permissions Use "but only if" conditions to fine-tune permissions Use IAM analyzer tools to verify and refine permissions on a regular basis What: Think in terms of data perimeter; only trusted identities accessing trusted resources from expected locations Never embed credentials into your configuration files Integrate with certificate authority services whenever possible On your journey to more secure IAM practices in your organization, remember GitGuardian is here to help you discover where those long-lived credentials have snuck into your code and files. Make sure you tackle secret sprawl as you are adopting better security practices.Download the cheat sheet
Vendor security assessments can be very complex, especially when it comes to analyzing modern solutions. Obsolete threat modeling principles and frameworks become extremely unreliable and tricky as complexity increases. Security analysis also becomes further intricate as it is not limited to the application's inherent design but also how it is integrated with any organization's core network. Implementation and configuration induces vulnerabilities in the system if security is not a part of the development lifecycle. Recent trends suggest that organizations are now moving to SASE solutions, replacing existing vendors that provide services like CASB (Cloud access security broker), DLP (Data Loss Prevention), proxy solutions, etc. What Is SASE? Secure Access Service Edge (SASE) is a framework that provides network convergence alongside security services. It adds security to the ingress and egress network traffic. The technology stack usually comprises CASB, DLP, SWG (Secure Web Gateway), FWaaS (Firewall as a Service), NGFW (Network Firewall), SDN (Software Defined Networking), and ZTNA (Zero Trust Network Architecture) solutions. Where Can We Utilize SASE Solutions? 1. Accessing Internet Securely: Organizations usually deploy proxy solutions at the user's workstation that direct HTTP and HTTPS traffic from endpoints to the internet. HTTPS traffic is decrypted at the proxy and processed through various security tools like DLP, IDS, etc. Note that some traffic passing through the proxy may include SSH and SFTP, which cannot be decrypted and are hence prone to threats. With a SASE solution in place, only traffic from approved sources is allowed. Also, the system has the capability to authenticate and inspect previously insecure protocols like SSH and SFTP. 2. Remote access and cloud access: Remote users can securely access internally, or cloud-hosted applications using features like remote secure connect. Moreover, SASE solutions can help replace CASB with the use of secure cloud access. How and What To Review for a SASE Solution Before any vendor is onboarded, it is very important to perform due diligence as a whole and architecturally review the application. One of the most effective review techniques that security architects follow is 'threat modeling.' There are multiple methods to create threat models, so implementations can vary by team. STRIDE (Spoofing, Tampering, Repudiation, Information disclosure, DoS, Elevation of privilege), PASTA (Process for Attack Simulation and Threat Analysis), and VAST (Visual, Agile, and Simple Threat) are some of the common methodologies used. Before a SASE solution can be considered, the first step is to understand the network. It is important to review an existing network diagram and understand changes to the data flow and the network itself. High-Level SASE network diagram Once the network diagram is updated, start by identifying potential threats for each entity. Then create a list of controls and map them to the threats. You need to ensure that all concerns are addressed. SASE threat modeling may sound very complex but can be completed easily by breaking it up into smaller steps. Below is an example of using the STRIDE methodology for reference: Entity 1: User Spoofing: Threat: User's credentials are compromised and being used by a malicious actor to connect to the system. Control: Enable MFA. Tampering: Threat: Brute force technique used to gain credentials. Control: Lock account after a specific number of failed attempts. Threat: Get access to the user's session. Control: Enable strong session management controls. Repudiation: Threat: No proof of wrongdoing by the threat agent. Control: Log and archive user activity. Information Disclosure: Threat: Information can be leaked from SASE hosting environment or through any connections going to and from SASE. Control: Only store the required user information; enable strong access and cryptographic controls; have a dedicated key for each tenant. Threat: Information can be leaked through connections going to and from SASE. Control: Use the secure protocol version, Block users or generate alerts for access over an insecure network. Denial of Service: Threat: End user unable to access the service due to bandwidth or license issues. Control: Enable scalability feature for SASE endpoint systems. Elevation of Privilege: Threat: User gains access to unauthorized data/service. Control: Set up RBAC (Role-based access control) for accessing internal applications. Threat: The user has illegal access. Control: Restrictive internet access. Entity 2: User Connectivity to SASE Spoofing: Threat: Accepting outside connection. Control: Verify the user before granting access. Tampering: Threat: Man in the middle attack. Control: Use the most up-to-date and secure protocol versions for communication. Repudiation: None Information Disclosure: Threat: Network Sniffing or password is disclosed. Control: Use the most secure protocols. Threat: User or link redirect. Control: Restrict internet access, and use black-and-white listing of IPs, URLs, domains, and applications. Denial of Service: Threat: Poor connectivity due to a large number of network hops. Control: Use a SASE provider with wider geographical coverage. Threat: Incompatible protocols used. Control: Use standard security protocols. Threat: Bandwidth issues. Control: Use bandwidth priority feature for critical applications. Elevation of Privilege: None Entity 3: Workstation Spoofing: Threat: Fraudulent device used. Control: Add security controls to check device identity before connecting. Tampering: Threat: Malware attack on workstation due to the user clicking on malicious links. Control: Enable malware analysis, inspect the files uploaded and isolate the browser on the SASE end. Threat: Direct connection bypassing SASE. Control: Monitor and restrict internet connections. Threat: Security control being disabled. Control: Allow only restricted user groups/admins to update user permissions. Repudiation: Threat: Lack of evidence and tracking of the compromised system. Control: Log and monitor activity; generate alert in case of suspicion. Threat: Missing information on the malicious activity on the workstation. Control: Enable endpoint detection and response. Information Disclosure: Threat: Leakage of sensitive information from the workstation. Control: Enable data loss prevention tools Denial of Service: None Elevation of Privilege: Threat: Workstation running with elevated privilege of SASE agent. Control: Restrict SASE agent's access; monitor privileged access closely. Entity 4: SASE Service and Its Hosting Solution Spoofing: Threat: Malicious endpoints hosted. Control: Establish trust before making connections. Threat: Admin account of SASE tenant and provider spoofed. Control: Use MFA for all admin connections. Tampering: Threat: Vulnerabilities exploited, including zero-day attacks. Control: Periodic pen tests and vulnerability assessment, including patching activity, should be conducted. Threat: Data and config modification. Control: Controlled change management procedure; enable RBAC with close monitoring for admin. Threat: Unauthorized physical access to data centers. Control: Enable badging and other physical security controls. Repudiation: Threat: Configuration changes could not be tracked or monitored. Control: Centralize SIEM solution and enforce strict change management policies. Threat: Could not identify the cause of unexpected issues. Control: Enforce enterprise-level monitoring and alerting. Information Disclosure: Threat: Data compromised and shared by a third party. Control: NDAs should be signed, and strong access management policies should be in place. Threat: Data not encrypted on hard drives and archives; data exposed in case of any required investigations. Control: Encrypt data at rest; tokenize and mask, if required. Denial of Service: Threat: Application not available due to network or application level Denial of Service attack. Control: Use WAF and CDN for DDoS prevention. Elevation of Privilege: Threat: Insider threat due to the SASE platform being compromised. Control: Set up the SASE application within the demilitarized zones (DMZs) and restrict the ingress traffic. Entity 5: Application/Internal Connections Through SASE Spoofing: Threat: SASE source spoofed. Control: Use mutual authentication techniques. Tampering: Threat: MiTM attack. Control: Use only secure protocol versions. Threat: Malicious data through the tunnel between SASE and data hosting environment. Control: Strong session management controls. Repudiation: Threat: Connections not being monitored. Control: Log every request to and from the SASE to target application Information Disclosure: Threat: Network Sniffing attack and password leakage Control: Access management and redirect traffic through private tunnels, Always use the latest and secure version of protocols Threat: Data leaked through the tunnel between SASE and the data hosting environment. Control: DLP and content inspection for the information flowing through the tunnel. Denial of Service: Threat: Broken network connection between the data center and SASE. Control: Multiple, alternative and reliable paths are created within the network. Elevation of Privilege: Threat: One tenant accessing system through other tenant's system/credentials. Control: RBAC; Each connection between tenants should be uniquely identifiable and can be controlled SASE solutions can be very useful to an organization, both from a security and business perspective. However, it is essential to understand where the data is hosted, who can access it, which controls are in place at the hosting location, and how the connectivity is made reliable and secure. Having a single solution helps teams centralize management and enable better coordination for various operational tasks. Industries advocate the use of SASE solutions, but it is important that implementation and operational risks are reviewed before onboarding the tool.
If you want to become a smart contract developer on Ethereum, then you need to learn Solidity. Whether your goal is DeFi, blockchain gaming, digital collectibles (NFTs), or just web3 in general, Solidity is the foundational language behind the innovative projects on Ethereum. But where should you start? In this article, we’ll look at 10 great ways you can learn Solidity. Whether you're a beginner or an experienced web2 developer, this guide will help you not only get started with Solidity, but master it. We’ll look at all the best online courses, tutorials, documentation, and communities that can help you on your journey. First, however, if you’re new to web3, let’s provide some background on Solidity. Why Learn Solidity? Solidity is the language for writing smart contracts on the world’s most popular smart contract blockchain, Ethereum. And it’s not just for Ethereum. Multiple other blockchains, such as Avalanche and Binance Smart Chain, and L2s, such as Polygon and Optimism, are powered by Solidity. Learning Solidity not only opens up opportunities for you in Ethereum but also overall in the growing field of blockchain development. It’s a perfect skill to have for web3! So let’s look at 10 great ways to learn Solidity. #1 - ConsenSys 10-Minute Ethereum Orientation For a quick and thorough introduction (especially if you’re new to blockchain and Ethereum), check out the 10-Minute Ethereum Orientation by ConsenSys. This is the perfect starting point to orient yourself with the key terms of web3, the web3 tech stack, and how Solidity works into it all. ConsenSys is the company behind the most popular technologies of the web3 stack—MetaMask (the leading wallet), Infura (the leading web3 API), Truffle (dev and testing tools for Ethereum smart contracts), Diligence (blockchain security company) and more. Solidity can be confusing—but these are the tools that make it easy to use. ConsenSys is a well-known source for learning and we’ll get into that more in point six. #2 - CryptoZombies Once you complete your intro, check out CryptoZombies. This is the OG resource for learning Solidity. It’s a fun, interactive game that teaches you Solidity through building your own crypto-collectibles game. It’s an excellent starting point for beginners who are interested in developing decentralized applications and smart contracts on Ethereum. The course provides an easy-to-follow, step-by-step tutorial that guides you through the process of writing Solidity smart contracts. It even has gamification elements to keep you motivated. And it’s updated regularly. As Solidity adds features, they also add new learning materials. Modules on Oracles and Zero-knowledge Proofs (zk technology) are some recent additions to the curriculum. #3 - Speedrun Ethereum Next is Speedrun Ethereum, a series of gamified quests for learning Solidity. These quests cover topics such as NFTs, DeFi, tokens, and more—and it’s a lot of fun! It even covers more advanced Solidity concepts, including higher-order functions and inheritance. This course is great for intermediate-level Solidity learners who are familiar with the basics of Solidity. #4 - Solidity by Example Solidity by Example is a free resource that focuses on well-written code samples to teach Solidity. It provides a wide range of these examples, with each example explained in detail. This is less of a course and more of a resource for learning clean Solidity syntax. Highly recommended. Code samples vary from some simple to very advanced concepts. A good example—and one you can learn a lot from—is the full UniswapV2 contract. #5 - Dapp University If video is more your style, Dapp University is a Youtube channel with over 10 hours of hands-on tutorials. The tutorials are designed for both beginners and experienced Solidity developers. The tutorials cover topics such as setting up the development environment, writing Solidity smart contracts, and deploying them to the Ethereum blockchain. The content is well-structured and provides easy-to-follow instructions that guide you through the process of building your own decentralized applications. #6 - ConsenSys Academy By the same company mentioned in #1, ConsenSys Academy offers several online courses such as, Blockchain Essentials created to kick start your Solidity developer journey. They also offer the Blockchain Developer Program On-Demand course, where you’ll learn about the underpinnings of blockchain technology and how it all comes together to allow us to build the next generation of web applications. You’ll learn about the types of smart contract code, introduce you to key development tools, and show you all the best practices for smart contract development, all to prepare you for the final project towards the end of the course. Learners get hands-on experience with tools like Infura and Truffle Ganache, which are some of the most popular and widely used development tools in the Ethereum ecosystem that are focused on making Solidity easy to use. And as a product of ConsenSys, the Developer Program provides a direct link to the ConsenSys ecosystem, with access to some of the best resources and tools in the industry. #7 - Udemy Ethereum Blockchain Developer Bootcamp With Solidity This is another bootcamp, but in the form of an extensive Udemy course. It provides learners with up-to-date blockchain development tools, resources, and complete, usable projects to work on. The course is taught by an instructor who is a co-creator of the industry-standard Ethereum certification. This course is also updated frequently to reflect the latest changes in the ecosystem. #8 - Certified Solidity Developer Of course, there is always the certification path. Certified Solidity Developer is a certification offered by the Blockchain Council. It’s expensive, but it provides learners with a solid foundation in Solidity and smart contract development—and that piece of paper. The certification is well-recognized and is one of the most highly-rated blockchain developer accreditations. The course also provides learners with a deep understanding of smart contracts, their design patterns, and the various security implications of writing and deploying them on the Ethereum network. #9 - Official Solidity Documentation The Solidity documentation should not be underestimated. It’s an essential resource for those learning Solidity. It has the added value of always being up to date with the latest version of Solidity, and it contains detailed information about the Solidity programming language. The documentation is available in nine different languages, including Chinese, French, Indonesian, Japanese, and others. Undoubtedly, you’ll come back again and again to the Solidity documentation as you learn, so bookmark it now. #10 - Solidity Communities and Forums Finally, there are several solidity communities and forums that are excellent resources, such as CryptoDevHub and Solidity Forum. These communities are composed of Solidity experts, developers, and learners at all different levels. Ask questions, share knowledge, and collaborate on Solidity projects. By participating in these communities, you can keep up-to-date with the latest developments, gain insights into how other developers are approaching Solidity development, and make a few friends! Learning Solidity—Just Get Started! That’s a great start to your path. Learning Solidity is a valuable investment in your career. With these resources, you should be well on your way to learning Solidity, joining web3, and writing and deploying your first smart contracts. Of course, the fastest way to learn is to jump right in—so go for it! Have a really great day!
Apostolos Giannakidis
Product Security,
Microsoft
Samir Behara
Senior Cloud Infrastructure Architect,
AWS
Boris Zaikin
Senior Software Cloud Architect,
Nordcloud GmBH
Anca Sailer
Distinguished Engineer,
IBM