<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: Eric Villa</title>
    <description>The latest articles on DEV Community by Eric Villa (@herrvilla).</description>
    <link>https://dev.to/herrvilla</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F477452%2F790ea028-6ad9-4e18-af3a-9ce5290c433f.jpeg</url>
      <title>DEV Community: Eric Villa</title>
      <link>https://dev.to/herrvilla</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/herrvilla"/>
    <language>en</language>
    <item>
      <title>IAM Users vs Roles</title>
      <dc:creator>Eric Villa</dc:creator>
      <pubDate>Thu, 17 Aug 2023 13:07:28 +0000</pubDate>
      <link>https://dev.to/aws-builders/iam-users-vs-roles-4i5o</link>
      <guid>https://dev.to/aws-builders/iam-users-vs-roles-4i5o</guid>
      <description>&lt;p&gt;In this blog post, we will cover IAM User and IAM Role concepts, focusing on best practices and access patterns.&lt;br&gt;
If you are already familiar with IAM User and Role concepts and just want to know what you should opt for based on your use case, feel free to skip to the last section: "When should I go for IAM Users and when for IAM Roles?".&lt;/p&gt;
&lt;h2&gt;
  
  
  What is an IAM User?
&lt;/h2&gt;

&lt;p&gt;When you create your first AWS account, you sign in with an identity that has full access to all the services and resources in your account. That identity is called the AWS account root user. As soon as you log into the AWS Console with the AWS account root user, you’ve to find a safer pattern to access it. Why? Because credentials associated with the AWS account root user are not disposable; in case of credentials theft, there is no way to invalidate them. That said, you can implement a safer access pattern by creating an IAM Identity called IAM User.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An AWS Identity and Access Management (IAM) user is an entity that you create in AWS. The IAM user represents the human user or workload who uses the IAM user to interact with AWS. A user in AWS consists of a name and credentials.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;A brand-new IAM User has, by default, no permissions. To allow an IAM User to access services and resources in the AWS account in which it was created, you’ve to assign an IAM Policy and one or more credentials to it.&lt;/p&gt;

&lt;p&gt;As explained in &lt;a href="https://blog.leapp.cloud/increase-aws-security-posture-with-iam-roles-and-policies" rel="noopener noreferrer"&gt;this&lt;/a&gt; article by my fellow colleague Alessandro Gaggia, an IAM Policy is a document that allows you to specify what an IAM Identity (in this case, an IAM User) can do on which resources or services, under what conditions. An IAM Policy is not enough to enable the IAM User permission to access resources or services; credentials must be associated with it.&lt;/p&gt;

&lt;p&gt;Based on the way you want to access AWS, you have to use different kinds of credentials.&lt;/p&gt;

&lt;p&gt;If you want to enable the IAM User to access the AWS Console, you’ve to assign a console password to the IAM User. The IAM User console password cannot be used to access AWS resources or services from the CLI or SDK.&lt;/p&gt;

&lt;p&gt;Access to services or resources from the CLI or SDK is called programmatic access. To grant the IAM User programmatic access, you’ve to set up Access Keys; Access Keys that are created and assigned to an IAM User are long-term credentials. It means they’ve no expiration; you can use them to access your AWS account until they’re disabled or deleted. A common best practice to avoid long-term credentials is to rotate IAM User’s Access Keys periodically by deleting the old ones and replacing them with new ones created from scratch. In addition, IAM User Access Keys can be used to generate temporary credentials through the AWS Security Token Service &lt;code&gt;GetSessionToken&lt;/code&gt; API.&lt;/p&gt;

&lt;p&gt;Another important common best practice consists in requiring multi-factor authentication for all IAM users in your account. With MFA, users must provide two forms of identification: a console password or Access Keys, and a temporary numeric code that's generated on a hardware device or by an application on a smartphone, like Google Authenticator.&lt;/p&gt;

&lt;p&gt;IAM Users are an effective instrument if you want to enable a human or application to access resources and services in a specific account, i.e. the one in which the IAM Users lives. But, there are many use cases that go beyond the possibilities of an IAM User. In particular, an IAM User does not fit a scenario in which we need to grant temporary permissions to trusted entities without sharing long-term credentials. Those trusted entities could be outside the boundary of my account (supposed that I have a single one), outside the boundary of AWS, or outside the boundary of my company.&lt;/p&gt;

&lt;p&gt;At this point, you may wonder what kind of technology you can exploit to overcome these limits.&lt;/p&gt;

&lt;p&gt;When it comes to granting temporary permissions to trusted entities without sharing long-term credentials, the IAM Identity that comes to the rescue is called IAM Role.&lt;/p&gt;
&lt;h2&gt;
  
  
  IAM Role
&lt;/h2&gt;

&lt;p&gt;An IAM Role is an Identity that you create in your AWS Account. Like an IAM User, an IAM Role has permissions defined in one or more IAM Access Policies associated with it. But, instead of being associated with one person or application, a Role is designed to be assumed by trusted entities. Assuming an IAM Role means generating temporary credentials associated with that IAM Role. These credentials allow us to perform operations against resources or services based on the permissions defined in the IAM Access Policy associated with the IAM Role.&lt;/p&gt;

&lt;p&gt;You can define which trusted entities are allowed to assume the role and acquire temporary security credentials using a Trust Policy for an IAM Role. In addition, the trust policy of a role defines the conditions under which the role can be assumed. The trust policy is written in JSON format and is attached to the role.&lt;/p&gt;

&lt;p&gt;Here's an example of what a trust policy for an IAM role might look like:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::YOUR_ACCOUNT_ID:root"
      },
      "Action": "sts:AssumeRole"
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Replace &lt;code&gt;YOUR_ACCOUNT_ID&lt;/code&gt; with your actual AWS account ID. In this trust policy, the Principal is set to the root user of the same AWS account (&lt;code&gt;arn:aws:iam::YOUR_ACCOUNT_ID:root&lt;/code&gt;). This means that any entity within the account can assume the role.&lt;/p&gt;

&lt;p&gt;Please note that while this example demonstrates granting access to any entity within the account, it's important to follow the principle of least privilege. Granting such broad permissions should be done with caution, as it might lead to unintended access and security risks. It's generally recommended to define more specific trust policies that only allow trusted entities that actually need the permissions provided by the role to assume it. It's important to craft trust policies carefully; trust policies, along with the permissions policies attached to the role, play a crucial role in controlling access to AWS resources in a secure and controlled manner.&lt;/p&gt;

&lt;p&gt;Let’s deepen some access scenarios in which I can use IAM Roles to grant temporary permissions to trusted entities.&lt;/p&gt;

&lt;h3&gt;
  
  
  Federated Access from External Identity Provider (IdP)
&lt;/h3&gt;

&lt;p&gt;In some organizations, user identities are managed outside of AWS using an Identity Provider (IdP). To provide users with access to AWS resources, you can enable federated access. This allows users authenticated by the external IdP to access your AWS environment without needing to create IAM Users. Instead, they're granted temporary access using security tokens based on their IdP authentication. This enhances security and reduces the need for separate user accounts in AWS. There are different kinds of federated access protocol, based on the IdP you’re using.&lt;/p&gt;

&lt;h3&gt;
  
  
  SAML Federated Access
&lt;/h3&gt;

&lt;p&gt;SAML (Security Assertion Markup Language) is a widely used protocol for SSO. When a user from your organization tries to access AWS resources, they authenticate with your external SAML-compatible IdP (such as Microsoft Active Directory Federation Services or Okta). After successful authentication, the IdP generates a SAML assertion, which is a digitally signed document containing the user's identity and attributes.&lt;/p&gt;

&lt;p&gt;The SAML assertion is passed to AWS through the &lt;code&gt;AssumeRoleWithSAML&lt;/code&gt; API call. This API call includes the Amazon Resource Name (ARN) of the IAM role the user wants to assume, along with the SAML assertion. AWS verifies the SAML assertion's signature and attributes with the trusted IdP metadata.&lt;/p&gt;

&lt;p&gt;If everything checks out, AWS issues temporary security credentials associated with the IAM role specified in the request. These credentials enable the user to access AWS services and resources according to the permissions defined in the IAM role's policies.&lt;/p&gt;

&lt;h3&gt;
  
  
  OpenID Connect Federated Access
&lt;/h3&gt;

&lt;p&gt;OpenID Connect (OIDC) is a modern protocol built on top of OAuth 2.0 that allows applications to authenticate users. When users want to access AWS resources, they authenticate with their OpenID Connect-compatible IdP. The IdP returns an ID token, which contains the user's identity and other relevant information.&lt;/p&gt;

&lt;p&gt;To enable federated access in AWS, you create an IAM identity provider that points to your OIDC IdP. Then, you create an IAM role with a trust policy that allows the OIDC identity provider to assume the role. Users initiate federated access by signing in through the IdP, and the OIDC token is exchanged for temporary AWS credentials through the &lt;code&gt;AssumeRoleWithWebIdentity&lt;/code&gt; API call.&lt;/p&gt;

&lt;h3&gt;
  
  
  Web Identity Federated Access
&lt;/h3&gt;

&lt;p&gt;Web identity providers include well-known platforms like Amazon, Facebook, Google, and more. These providers offer their own authentication mechanisms for user sign-ins. When a user authenticates with one of these providers, they receive an identity token.&lt;/p&gt;

&lt;p&gt;Similar to OIDC, you establish an IAM identity provider for the web identity provider. You create an IAM role with a trust policy allowing the web identity provider to assume the role. Users authenticated by the web identity provider can assume the role using the &lt;code&gt;AssumeRoleWithWebIdentity&lt;/code&gt; API call, receiving temporary AWS credentials to access resources based on the role's permissions.&lt;/p&gt;

&lt;h3&gt;
  
  
  Cross-Account Access
&lt;/h3&gt;

&lt;p&gt;Traditionally, managing access to resources across different AWS accounts could be complex and potentially compromise security by sharing long-term credentials. However, AWS cross-account access with IAM roles simplifies this process while enhancing security and control. It empowers organizations to collaborate seamlessly, allowing users from one AWS account to access resources in another account with well-defined permissions.&lt;/p&gt;

&lt;p&gt;This capability is particularly valuable for scenarios such as:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Organizational Collaboration:&lt;/strong&gt; different departments, teams, or external partners can work together effectively by granting controlled access to specific resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Managed Services:&lt;/strong&gt; organizations can centralize operations by providing external services, like managed security or analytics, and secure access to resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Consulting and Vendor Engagement:&lt;/strong&gt; consulting companies or vendors can access client resources while adhering to stringent security practices.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The core concept behind AWS cross-account access is the utilization of IAM roles. Instead of sharing credentials, a trusted relationship is established between accounts. The trusting account defines an IAM role with a Trust Policy that allows IAM Identities in the trusted account to assume that role.&lt;/p&gt;

&lt;p&gt;Let's say Account A (123456789012) wants to allow users from Account B (987654321001) to access specific resources. Account A creates an IAM role named &lt;code&gt;CrossAccountRoleA&lt;/code&gt; and attaches a Trust Policy that specifies that Account B is allowed to assume this role.&lt;/p&gt;

&lt;p&gt;Trust Policy for &lt;code&gt;CrossAccountRoleA&lt;/code&gt; in Account A:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
  "Version": "2012-10-17",
  "Statement": [
    {
      "Effect": "Allow",
      "Principal": {
        "AWS": "arn:aws:iam::987654321001:root"
      },
      "Action": "sts:AssumeRole",
      "Condition": {}
    }
  ]
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In Account B (987654321001), IAM users or roles can assume the &lt;code&gt;CrossAccountRoleA&lt;/code&gt; role from Account A (123456789012) because Account A has defined a trust policy allowing it. Users in Account B can use the &lt;code&gt;AssumeRole&lt;/code&gt; API call to acquire temporary credentials for the &lt;code&gt;CrossAccountRoleA&lt;/code&gt; role.&lt;/p&gt;

&lt;p&gt;Assuming &lt;code&gt;CrossAccountRoleA&lt;/code&gt; in Account B using AWS CLI:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws sts assume-role --role-arn arn:aws:iam::123456789012:role/CrossAccountRoleA --role-session-name MySession
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This will return temporary security credentials that can be used to access resources in Account A.&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS Service-to-Service Access
&lt;/h3&gt;

&lt;p&gt;AWS services often need to interact with each other for various purposes. For example, you might want an AWS Lambda function to access data stored in Amazon S3. Instead of relying on long-term credentials, you can create an IAM role with the required permissions and allow the Lambda function to assume that role. This enables the Lambda function to securely access the necessary resources without exposing sensitive credentials.&lt;/p&gt;

&lt;p&gt;Here's a concise breakdown of how AWS Service-to-Service Access works:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Role Creation:&lt;/strong&gt; create an IAM role with necessary permissions for an AWS service to perform specific actions on other AWS resources.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Trust Policy:&lt;/strong&gt; specify the AWS service's ARN in the role's trust policy, allowing it to assume the role.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Role Assumption:&lt;/strong&gt; the AWS service requests temporary credentials from AWS STS by assuming the role.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Temporary Credentials:&lt;/strong&gt; AWS STS provides temporary credentials, including the Access Key ID, the Secret Access Key, and the Session Token.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Resource Access:&lt;/strong&gt; the AWS service uses temporary credentials to interact securely with other AWS resources.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h3&gt;
  
  
  EC2 Instance Access without Long-Term Credentials
&lt;/h3&gt;

&lt;p&gt;On 12 June 2014, Mike Pope announced a new, crucial AWS feature: &lt;a href="https://aws.amazon.com/blogs/security/granting-permission-to-launch-ec2-instances-with-iam-roles-passrole-permission/" rel="noopener noreferrer"&gt;Granting Permission to Launch EC2 Instances with IAM Roles&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you deploy a workload on an EC2 instance that requires access to AWS services, instead of embedding IAM User’s long-term credentials (Access Keys) directly into the instance, which can pose security risks, you can assign an IAM role to it. This role grants temporary permissions to the EC2 instance, ensuring that the workload running on this instance can interact with AWS services securely without exposing credentials. This dynamic and controlled approach simplifies management and enhances security.&lt;/p&gt;

&lt;p&gt;When creating the IAM Role that has to be attached to the EC2 instance, remember to add a Trust Policy that allows the trusted entity (in this case, the EC2 service) to assume the role. In particular, you’ve to add &lt;code&gt;"Service": "ec2.amazonaws.com"&lt;/code&gt; as the Principal in the Trust Policy.&lt;/p&gt;

&lt;p&gt;The IAM Role can be attached to the instance during its creation or when it is already running.&lt;/p&gt;

&lt;p&gt;When you assign an IAM role to an EC2 instance, an instance profile is automatically created. This instance profile is associated with the IAM role and acts as a container for temporary security credentials. The instance profile is managed by AWS and is not directly accessible from outside the instance.&lt;/p&gt;

&lt;p&gt;When an application or process running on the EC2 instance needs to access AWS services, it makes an HTTP request to the metadata service, which is a web service that provides information about the instance's configuration and attributes. In this case, the &lt;code&gt;http://169.254.169.254/latest/meta-data/iam/security-credentials/&amp;lt;role-name&amp;gt;&lt;/code&gt; endpoint is invoked to retrieve temporary security credentials associated with the IAM role. These credentials include an Access Key ID, a Secret Access Key, a Session Token, and an Expiration Time. EC2 instances automatically renew the temporary credentials by periodically requesting updated credentials from the metadata service. This ensures uninterrupted access to AWS resources.&lt;/p&gt;

&lt;h2&gt;
  
  
  Interaction between IAM Users and IAM Roles
&lt;/h2&gt;

&lt;p&gt;As far as now, we didn’t take into account any possible interaction between IAM Users and IAM Roles. Well, IAM users can interact with IAM roles through the process of assuming roles. This allows IAM users to temporarily take on the permissions and privileges associated with an IAM role, granting them access to resources they might not have direct permissions. This interaction is commonly used to delegate access to specific resources without sharing long-term credentials.&lt;/p&gt;

&lt;p&gt;An IAM User initiates the process by calling the &lt;code&gt;AssumeRole&lt;/code&gt; API, specifying the ARN (Amazon Resource Name) of the IAM Role they want to assume. The IAM User must have the necessary permissions to assume the role in the first place. These permissions are defined by an IAM Access Policy attached to the user. The IAM Role’s Trust Policy must contain a statement that allows the IAM User to assume it. If the trust policy allows the IAM User to assume the role, AWS STS (Security Token Service) generates temporary credentials for the IAM User. The IAM User can use the temporary credentials to make requests to AWS services just like they would with their own IAM User credentials. The IAM User only has the permissions associated with the assumed role, not their original IAM User permissions.&lt;/p&gt;

&lt;p&gt;As previously mentioned, it is possible to enable MFA for an IAM User. In the user's Access Policy, you can define actions that require MFA protection. This means that these actions can only be performed using IAM User credentials that include MFA information.&lt;/p&gt;

&lt;p&gt;To generate credentials that include MFA information, you must call the STS &lt;code&gt;GetSessionToken&lt;/code&gt; API and provide a valid MFA token associated with a hardware or virtual MFA device. You can then use the resulting credentials to call MFA-protected actions.&lt;/p&gt;

&lt;h2&gt;
  
  
  When should I go for IAM Users and when for IAM Roles?
&lt;/h2&gt;

&lt;h3&gt;
  
  
  IAM Users
&lt;/h3&gt;

&lt;p&gt;IAM Users are well-suited for managing access within your AWS account, particularly for individuals and applications that require straightforward access to AWS services and resources. They offer personalized access control and are appropriate for the following scenarios:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Individuals:&lt;/strong&gt; If you have human users who need to interact with AWS services using the AWS Management Console, IAM Users provide a way to grant personalized access. You can assign permissions based on each user's roles and responsibilities.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Simple Application Access:&lt;/strong&gt; For applications running within your AWS account that require programmatic access to AWS services, IAM Users can be used. However, it's important to note that IAM Roles are often a better choice for applications, as they provide temporary access without exposing long-term credentials.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While IAM Users are useful for straightforward access requirements, they might not be the optimal solution for scenarios involving temporary access, cross-account access, or enhanced security.&lt;/p&gt;

&lt;h3&gt;
  
  
  IAM Roles
&lt;/h3&gt;

&lt;p&gt;IAM Roles offer a more comprehensive approach to access management, particularly when dealing with complex access patterns and security considerations. They are the recommended choice in the following situations:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Federated Access:&lt;/strong&gt; When you need to grant temporary access to users from external identity providers (IdPs) such as SAML, OpenID Connect, or web identity providers, IAM Roles provide a secure way to authenticate and access AWS resources without exposing long-term credentials.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Cross-Account Access:&lt;/strong&gt; IAM Roles excel at enabling secure collaboration between AWS accounts. This is crucial for scenarios like organizational partnerships, managed services, and consulting engagements.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;&lt;strong&gt;Service-to-Service Access:&lt;/strong&gt; IAM Roles facilitate secure interactions between AWS services without relying on long-term credentials. This enhances security and adheres to the principle of least privilege.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;IAM Roles streamline security, minimize long-term credential exposure, and provide controlled access. They're designed to address a wide range of security and access requirements.&lt;/p&gt;

&lt;p&gt;In summary, while IAM Users are suitable for simpler access scenarios within an AWS account, IAM Roles offer a more advanced and secure approach for managing complex access patterns, temporary access needs, and cross-account collaboration. The choice between IAM Users and IAM Roles should align with the specific security requirements and complexity of the access scenario you're addressing.&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s all Folks!
&lt;/h2&gt;

&lt;p&gt;In this blog post we have seen what are IAM Users and IAM Roles, what are the differences between them, and the use cases in which they’re used.&lt;/p&gt;

&lt;p&gt;I hope you enjoyed this blog post and that you find it informative. Please, don’t hesitate to provide your feedback and share your thoughts about the topic. Feel free to reach out to us on our &lt;a href="https://join.slack.com/t/noovolari/shared_invite/zt-opn8q98k-HDZfpJ2_2U3RdTnN~u_B~Q" rel="noopener noreferrer"&gt;Community Slack&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Stay tuned for new publications!&lt;/p&gt;

</description>
      <category>identity</category>
      <category>aws</category>
      <category>security</category>
    </item>
    <item>
      <title>Who am I in AWS? Presenting IAM STS get-caller-identity</title>
      <dc:creator>Eric Villa</dc:creator>
      <pubDate>Thu, 01 Jun 2023 15:44:29 +0000</pubDate>
      <link>https://dev.to/aws-builders/who-am-i-in-aws-presenting-iam-sts-get-caller-identity-3m2e</link>
      <guid>https://dev.to/aws-builders/who-am-i-in-aws-presenting-iam-sts-get-caller-identity-3m2e</guid>
      <description>&lt;p&gt;Have you ever been in a situation in which you were about to forward a critical API request to AWS but you were not sure what was the target of your request?&lt;/p&gt;

&lt;p&gt;It’s always a best practice to check if the API request target is the one that you expect, especially if the operations that are about to be performed may have major repercussions on your AWS accounts.&lt;/p&gt;

&lt;h2&gt;
  
  
  Who am I in the context of AWS?
&lt;/h2&gt;

&lt;p&gt;When it comes generate temporary credentials and get information about them, AWS Security Token Service (AWS STS) comes to the rescue.&lt;/p&gt;

&lt;p&gt;“Who am I in the context of AWS” is exactly the question the AWS STS GetCallerIdentity API provides an answer to. The answer tells you what is the account affected by the next API call if credentials are not going to change in the meanwhile.&lt;/p&gt;

&lt;p&gt;Yes, I mentioned AWS STS. Indeed, this is the service that I should call upon to get that information. To interface with the GetCallerIdentity API, two requirements must be fulfilled:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;network connectivity;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;a valid set of AWS Credentials, placed in one of the locations the client that you’re using expects them to be (environment variables, shared configuration files, etcetera). As you can see on &lt;a href="https://docs.aws.amazon.com/STS/latest/APIReference/API_GetCallerIdentity.html" rel="noopener noreferrer"&gt;this&lt;/a&gt; documentation page, authentication information is added to the request via the Authorization Header.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The reference client used in this article is the AWS CLI (Command Line Interface). The AWS CLI command that you should issue to get this information is the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;aws sts get-caller-identity
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h2&gt;
  
  
  aws sts get-caller-identity response structure
&lt;/h2&gt;

&lt;p&gt;Regardless of the IAM identity used to authenticate the request, the API response always contains three fields:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;UserId - the unique identifier of the calling entity;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Account - the AWS Account ID number of the account that owns or contains the calling entity;&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Arn - the Amazon Resource Name associated with the calling identity.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;While the Account field is always a 12-digits number, Arn and UserId depend on the principal that initiated the request.&lt;/p&gt;

&lt;p&gt;In this blog post, we’ll focus on two categories of principals: User and AssumedRole.&lt;/p&gt;

&lt;p&gt;The User category simply corresponds to the IAM User principal.&lt;/p&gt;

&lt;p&gt;The AssumedRole category covers more principals, but we’ll focus on SAML federated user (assumed via AssumeRoleWithSAML API), assumed role (assumed via AssumeRole API), and role assigned to an Amazon EC2 instance.&lt;/p&gt;

&lt;p&gt;For a complete overview of principals, please refer to the &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/reference_policies_variables.html#principaltable" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Now, let’s deepen the UserId and Arn fields for each of the previously cited principals.&lt;/p&gt;

&lt;h3&gt;
  
  
  IAM User
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "UserId": "AIDACKCEVSQ6C2EXAMPLE",
    "Account": "123456789012",
    "Arn": "arn:aws:iam::123456789012:user/JohnDoe"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The UserId corresponds to the unique ID of the IAM User.&lt;/p&gt;

&lt;p&gt;The Arn field adheres to the following template: &lt;code&gt;arn:aws:iam::&amp;lt;account-id&amp;gt;:user/&amp;lt;user-name-with-path&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  SAML federated user
&lt;/h3&gt;



&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "UserId": "AROACKCEVSQ6C2EXAMPLE:johndoe@example.com",
    "Account": "123456789012",
    "Arn": "arn:aws:sts::123456789012:assumed-role/john.doe/johndoe@example.com"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The UserId consists of the unique ID of the role (AROACKCEVSQ6C2EXAMPLE) and the caller specified role name (&lt;a href="mailto:johndoe@example.com"&gt;johndoe@example.com&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;The caller specified role name corresponds to the RoleSessionName attribute that is part of the SAML assertion.&lt;/p&gt;

&lt;p&gt;The SAML assertion is an authentication response forwarded by the external IdP to the &lt;code&gt;https://region-code.signin.aws.amazon.com/saml&lt;/code&gt; endpoint. The SAML assertion contains a set of claims; the RoleSessionName is one of them.&lt;/p&gt;

&lt;p&gt;Typically, the value of the RoleSessionName attribute is a user ID or an email address. As explained in &lt;a href="https://blog.leapp.cloud/how-to-saml-federate-your-aws-account-with-g-suite" rel="noopener noreferrer"&gt;this&lt;/a&gt; blog post by my fellow colleague &lt;a href="https://twitter.com/NicoloMarchesi" rel="noopener noreferrer"&gt;Nicolò Marchesi&lt;/a&gt;, when it comes to federating a G Suite IdP to an AWS account, the RoleSessionName SAML attribute is mapped to the G Suite user’s Primary Email.&lt;/p&gt;

&lt;p&gt;The Arn field adheres to the following template: &lt;code&gt;arn:aws:iam::&amp;lt;account-id&amp;gt;:assumed-role/&amp;lt;role-name&amp;gt;/&amp;lt;role-session-name&amp;gt;&lt;/code&gt;. The Principal Type is not a user - as for the IAM User - but an assumed-role. Indeed, the SAML-based federation allows a user - managed by the external IdP - to assume an AWS Role via the STS assumeRoleWithSAML API.&lt;/p&gt;

&lt;h3&gt;
  
  
  Assumed role
&lt;/h3&gt;

&lt;p&gt;This principal corresponds to an IAM Role assumed via the AssumeRole API. Using this API, an IAM Role can be assumed by either an IAM User, an AWS IAM Identity Center user, or another IAM Role (the last configuration is called role chaining).&lt;/p&gt;

&lt;p&gt;All these configurations provide the same GetCallerIdentity API response structure.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{
    "UserId": "AROACKCEVSQ6C2EXAMPLE:FakeRoleSessionName",
    "Account": "123456789012",
    "Arn": "arn:aws:sts::123456789012:assumed-role/FakeRoleName/FakeRoleSessionName"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As for the SAML federated user scenario, the Arn field adheres to the following template: &lt;code&gt;arn:aws:iam::&amp;lt;account-id&amp;gt;:assumed-role/&amp;lt;role-name&amp;gt;/&amp;lt;role-session-name&amp;gt;&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;The UserId field is composed of the unique id of the role and the caller specified role name that is specified by the RoleSessionName parameter passed to the AssumeRole request.&lt;/p&gt;

&lt;h3&gt;
  
  
  Role assigned to an Amazon EC2 instance
&lt;/h3&gt;

&lt;p&gt;When you launch an Amazon EC2 instance, you specify an IAM role to associate with the instance. Applications that run on the instance can then use the role-supplied temporary credentials to sign API requests. To be precise, the IAM Role is encapsulated in an Instance Profile which can provide the role’s temporary credentials to an application that runs on the instance.&lt;/p&gt;

&lt;p&gt;When you call the AWS STS GetCallerIdentity API, the request is signed using the temporary credentials supplied via the Instance Profile. The following is an example response.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;{&lt;br&gt;
    "Account": "123456789012",&lt;br&gt;
    "UserId": "AROACKCEVSQ6C2EXAMPLE:i-1234567890abcdef0",&lt;br&gt;
    "Arn": "arn:aws:sts::123456789012:assumed-role/iam-role-name/i-1234567890abcdef0"&lt;br&gt;
}&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;The UserId field is composed of the unique id of the role (AROACKCEVSQ6C2EXAMPLE) and the unique identifier of the EC2 instance (i-1234567890abcdef0).&lt;/p&gt;

&lt;p&gt;The Arn field adheres to the following template: &lt;code&gt;arn:aws:iam::&amp;lt;account-id&amp;gt;:assumed-role/&amp;lt;role-name&amp;gt;/&amp;lt;role-session-name&amp;gt;&lt;/code&gt;. The  corresponds to iam-role-name while the  corresponds to the unique identifier of the EC2 instance.&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s all Folks!
&lt;/h2&gt;

&lt;p&gt;In this blog post, I’ve provided you with a description of the API that you can consume to answer the question “Who am I in the context of AWS?”. The answer to that question can vary, depending on the Principal associated with the IAM Credentials used to sign the GetCallerIdentity API.&lt;/p&gt;

&lt;p&gt;Reach out to &lt;a href="https://twitter.com/herr_villa" rel="noopener noreferrer"&gt;me&lt;/a&gt;, if you want to enrich the list of most common scenarios where you can find yourself in.&lt;/p&gt;

&lt;p&gt;Stay tuned for new publications!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>identity</category>
      <category>devops</category>
    </item>
    <item>
      <title>Fixing botocore.exceptions.nocredentialserror: unable to locate credentials [SOLVED]</title>
      <dc:creator>Eric Villa</dc:creator>
      <pubDate>Mon, 06 Mar 2023 16:25:48 +0000</pubDate>
      <link>https://dev.to/aws-builders/fixing-botocoreexceptionsnocredentialserror-unable-to-locate-credentials-solved-p15</link>
      <guid>https://dev.to/aws-builders/fixing-botocoreexceptionsnocredentialserror-unable-to-locate-credentials-solved-p15</guid>
      <description>&lt;p&gt;If you saw this error while running a Python script or application, you stumbled upon one of the most common errors that arise when boto3 is unable to locate valid AWS credentials needed to sign an API call to a specific AWS service.&lt;/p&gt;

&lt;p&gt;There are many StackOverflow questions about that:&lt;/p&gt;

&lt;p&gt;This error is specific to Python; if you’re looking for a solution to the “Unable to locate credentials” issue we’ve already written a &lt;a href="https://blog.leapp.cloud/aws-sdk-unable-to-locate-credentials" rel="noopener noreferrer"&gt;blog post&lt;/a&gt; about that.&lt;/p&gt;

&lt;p&gt;Before calling an API, you need to create a client specific to the service you want to use.&lt;/p&gt;

&lt;p&gt;The most traditional way to instantiate a service client consists in using one of the following abstractions provided by the boto3 SDK:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;boto3.&lt;strong&gt;client&lt;/strong&gt;('s3');&lt;/li&gt;
&lt;li&gt;boto3.&lt;strong&gt;resource&lt;/strong&gt;('s3').&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Regardless of the type of abstraction, a new default boto3.session.Session is created unless another one is already instantiated. If you are wondering what a boto3.session.Session object is, I suggest referring to its documentation:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A session stores configuration state and allows you to create service clients and resources.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  A simple example
&lt;/h2&gt;

&lt;p&gt;To reproduce the error, let me use an example script that invokes the Amazon S3 API that returns the list of all buckets owned by the authenticated sender of the request.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import boto3

s3_client = boto3.client("s3")

list_buckets_response = s3_client.list_buckets()["Buckets"]
bucket_names = ", ".join(list(map(lambda bucket: bucket["Name"], list_buckets_response)))

print(bucket_names)

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As I previously said, when &lt;code&gt;boto3.client("s3")&lt;/code&gt; instruction is executed, and a new default session object is created; this session object wraps AWS credentials info too. You can easily deduce that if boto3 is not able to locate credentials, the &lt;em&gt;botocore.exceptions.NoCredentialsError&lt;/em&gt; error is thrown. In this scenario, executing the previous script will produce an output similar to the following:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fufj2u6d3lf0j1vyly8kn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fufj2u6d3lf0j1vyly8kn.png" width="800" height="399"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Where is boto3 looking for credentials?
&lt;/h2&gt;

&lt;p&gt;boto3 searches for AWS credentials through a list of possible locations until it finds valid ones.&lt;/p&gt;

&lt;p&gt;As described in the &lt;a href="https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html" rel="noopener noreferrer"&gt;documentation&lt;/a&gt;:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;p&gt;Boto3 gives higher priority to credentials passed as parameters during client initialization.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If credentials are not provided this way, it looks for them inside environment variables and shared configuration files (i.e., ~/.aws/credentials and ~/.aws/config files).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;If it’s still unable to get valid credentials, it tries to obtain them through the Instance Metadata Service on an Amazon EC2 instance with an IAM role configured.&lt;/p&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Again, &lt;em&gt;botocore.exceptions.NoCredentialsError&lt;/em&gt; is raised if boto3 is unable to find valid AWS credentials in any of the listed locations.&lt;/p&gt;

&lt;h2&gt;
  
  
  Let's find a solution!
&lt;/h2&gt;

&lt;p&gt;To solve the issue, I’ll generate a set of temporary credentials associated with a specific IAM User. Generating temporary credentials for an IAM User involves calling the STS get-session-token API. I let &lt;a href="https://www.leapp.cloud" rel="noopener noreferrer"&gt;Leapp&lt;/a&gt; generate them automatically for me.&lt;/p&gt;

&lt;p&gt;Once set up, boto3 should be able to obtain valid AWS credentials from the ~/.aws/credentials file. Let’s try running the Python script again.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi15ffn9zq2msrqp5a3e4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fi15ffn9zq2msrqp5a3e4.png" width="800" height="96"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As expected, boto3 found a valid set of temporary credentials in the &lt;em&gt;~/.aws/credentials&lt;/em&gt; file. It used those credentials to sign the Amazon S3 API request and obtain the list of buckets owned by the authenticated sender of the request.&lt;/p&gt;

&lt;h2&gt;
  
  
  Boto3 Session: The Icing on the Cake
&lt;/h2&gt;

&lt;p&gt;What about long-running scripts? What if the script tries to access the Amazon S3 list bucket API, but the first set of credentials loaded by boto3 is expired? Well, it will not be able to forward the request.&lt;/p&gt;

&lt;p&gt;The problem is that using only boto3.client or boto3.resource module-level functions, the first set of credentials is wrapped into a &lt;strong&gt;default&lt;/strong&gt; boto3.session.Session object that will not be refreshed.&lt;/p&gt;

&lt;p&gt;To keep credentials always aligned with those found in one of the Credentials Provider Chain locations, you can instantiate a boto3.session.Session objects directly and obtains new Amazon S3 clients from it as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;import boto3

while True:
  input("type a key to list the available Amazon S3 buckets")

  s3_client = boto3.session.Session().client("s3")

  try:
    buckets = s3_client.list_buckets()["Buckets"]
    bucket_names = ", ".join(list(map(lambda bucket: bucket["Name"], buckets)))
    print(bucket_names)
  except Exception as e:
    print(e)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To emulate a long-running script, I introduced a while loop that starts by asking the user to type a key to run the n-th iteration. That way, we can control credentials availability by starting/stopping the Leapp Session before the n-th iteration is triggered.&lt;/p&gt;

&lt;p&gt;At this point, let’s run the script by leaving the Leapp Session stopped; it returns the following output.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwpvzwufvwjot510j5dqv.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fwpvzwufvwjot510j5dqv.png" width="800" height="145"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;As you can see, it was unable to locate credentials as, at the time the 1st iteration was triggered, credentials were not available in any of the Credentials Provider Chain locations.&lt;/p&gt;

&lt;p&gt;And now, let’s start the Leapp Session.&lt;/p&gt;

&lt;p&gt;At this point, a new set of temporary credentials associated in the ~/.aws/credentials file.&lt;/p&gt;

&lt;p&gt;By triggering the 2nd iteration, we got the following output from the script:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnkb3cslly8t310bc3yb.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fdnkb3cslly8t310bc3yb.png" width="800" height="201"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;During the 2nd iteration, boto3 was able to instantiate a new Session object from a valid set of AWS credentials located in the ~/.aws/credentials file. Therefore, it could sign and forward the request to the Amazon S3 bucket endpoint to obtain the list of buckets owned by the authenticated sender.&lt;/p&gt;

&lt;p&gt;I can fine-tune the previous script to maintain a single instance of the Session object and re-instantiate it only if the credentials used to sign the request are expired.&lt;/p&gt;

&lt;p&gt;So, my suggestion is to use the boto3.session.Session objects, as instantiating, is an elegant way to refresh credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s all, Folks!
&lt;/h2&gt;

&lt;p&gt;I hope you found all the information you needed to understand and solve the botocore.exceptions.NoCredentialsError!&lt;/p&gt;

&lt;p&gt;As a takeout, consider refactoring your existing code to adopt the boto3.session.Session object unless you are already using it. It could be a game-changer, especially in long-running scripts.&lt;/p&gt;

&lt;p&gt;This article is part of this blog's “&lt;a href="https://blog.leapp.cloud/series/how-to-fix" rel="noopener noreferrer"&gt;IAM how to fix&lt;/a&gt;” series.&lt;/p&gt;

&lt;p&gt;Stay updated with your IAM expertise by &lt;a href="https://blog.leapp.cloud/newsletter" rel="noopener noreferrer"&gt;subscribing to our newsletter&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;Share your thoughts and feedback about this blog post in a comment or by reaching out to me through my &lt;a href="https://twitter.com/herr_villa" rel="noopener noreferrer"&gt;Twitter profile&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;If you liked the Leapp experience, give us a star!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>python</category>
      <category>boto3</category>
      <category>identity</category>
    </item>
    <item>
      <title>What are AWS credentials?</title>
      <dc:creator>Eric Villa</dc:creator>
      <pubDate>Tue, 17 Jan 2023 14:39:16 +0000</pubDate>
      <link>https://dev.to/aws-builders/what-are-aws-credentials-13p1</link>
      <guid>https://dev.to/aws-builders/what-are-aws-credentials-13p1</guid>
      <description>&lt;p&gt;John: “Hey Eric, I need to access project-xyz dev account! Can you help me in some way?”&lt;/p&gt;

&lt;p&gt;Me: “Sure, but what kind of access do you need?”&lt;/p&gt;

&lt;p&gt;John:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw4dyqsdjq5xqr50sztg1.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fw4dyqsdjq5xqr50sztg1.gif" width="292" height="307"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Dear John, there are two kinds of access to AWS:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;via Web Console;&lt;/li&gt;
&lt;li&gt;programmatic.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Web Console access
&lt;/h2&gt;

&lt;p&gt;This type of access requires you to log into your AWS account using your preferred browser.&lt;/p&gt;

&lt;p&gt;When I set up my first AWS account, I logged into it as a &lt;strong&gt;root user&lt;/strong&gt; using my browser. The first thing I did was create a brand new &lt;strong&gt;admin IAM User&lt;/strong&gt; and enable Web Console access for it.&lt;/p&gt;

&lt;p&gt;Why? Because managing root user credentials is too dangerous, as you can’t disable them once stolen… get it? So, use them to create an &lt;strong&gt;admin IAM User&lt;/strong&gt;, store them in your password manager, and simply forget about them.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6412kc07g21tmcgvprca.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F6412kc07g21tmcgvprca.gif" width="250" height="188"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Let me share with you two docs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html" rel="noopener noreferrer"&gt;creating an IAM User in your AWS account&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/console.html#user-sign-in-page" rel="noopener noreferrer"&gt;signing into the AWS Web Console as an IAM User or root user&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In 2018 AWS introduced AWS Organizations, a service that lets you consolidate and centrally manage multiple AWS Accounts. It is a best practice to govern access to these accounts through AWS Organizations’ preferred buddy: AWS SSO.&lt;/p&gt;

&lt;p&gt;AWS SSO lets you create and manage a dedicated pool of users unless you want to federate it with an external Identity Provider.&lt;/p&gt;

&lt;p&gt;Users can access the AWS Management Console via the so-called Portal URL, which looks similar to the following one:&lt;/p&gt;

&lt;p&gt;&lt;em&gt;&lt;a href="http://d-012345dee0.awsapps.com/start" rel="noopener noreferrer"&gt;d-012345dee0.awsapps.com/start&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;For sake of completeness, let me add SAML 2.0 federated access to the previously described ways of accessing an AWS account from the Web Console.&lt;/p&gt;

&lt;p&gt;If you want to dig into SAML 2.0 federated access to AWS, give a look at &lt;a href="https://medium.com/leapp-cloud/how-to-saml-federate-your-aws-account-with-g-suite-6619f6b35507" rel="noopener noreferrer"&gt;this&lt;/a&gt; blog post by my fellow colleague &lt;a href="https://twitter.com/NicoloMarchesi" rel="noopener noreferrer"&gt;Nicolò Marchesi&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;And now… Ladies &amp;amp; Gentlement, programmatic access!&lt;/p&gt;

&lt;h2&gt;
  
  
  Programmatic access
&lt;/h2&gt;

&lt;p&gt;When you talk about AWS credentials, you probably refer to this kind of access, not the Web Console-based one.&lt;/p&gt;

&lt;p&gt;Well, as you might guess, AWS credentials are included in the browser too when accessing an AWS account via Web Console; yes, through dedicated HTTP cookies.&lt;/p&gt;

&lt;p&gt;What does programmatic access actually mean?&lt;/p&gt;

&lt;p&gt;Programmatic access refers to accessing an AWS account by the means of a client, i.e. an AWS SDK or the AWS CLI.&lt;/p&gt;

&lt;p&gt;These clients rely on AWS credentials to add authentication information to the HTTP calls sent to AWS APIs. Without this information, AWS won’t allow you to access your account. In particular, the AWS credentials we’re referring to are called Access Keys.&lt;/p&gt;

&lt;h2&gt;
  
  
  Access Keys
&lt;/h2&gt;

&lt;p&gt;So, Access Keys are AWS credentials used by AWS SDKs or by the AWS CLI to add authentication information to &lt;strong&gt;programmatic&lt;/strong&gt; HTTP calls sent to AWS APIs.&lt;/p&gt;

&lt;p&gt;There are two types of Access Keys out there: &lt;strong&gt;long-term&lt;/strong&gt; and &lt;strong&gt;temporary&lt;/strong&gt; ones.&lt;/p&gt;

&lt;p&gt;Long-term credentials are the ones that are bound to a specific IAM User. Long-term credentials do not expire; therefore, as a best practice, it is warmly recommended to rotate them regularly.&lt;/p&gt;

&lt;p&gt;On the other hand, temporary (or short-term) credentials are time-limited; therefore, if they’re associated with an IAM permission that is designed with Least Privilege in mind, they reduce your AWS account/s exposure to attackers.&lt;/p&gt;

&lt;p&gt;Be careful: sometimes applying these best practices is not enough to prevent &lt;a href="https://rhinosecuritylabs.com/aws/aws-privilege-escalation-methods-mitigation/" rel="noopener noreferrer"&gt;privilege escalation&lt;/a&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  Where can Access Keys be found?
&lt;/h3&gt;

&lt;p&gt;The answer to this question is quite simple. Access Keys can be found in all those places where the clients are programmed to look credentials for. These places (or sources) are mapped into the Credentials Provider Chain, as explained in &lt;a href="https://medium.com/leapp-cloud/aws-credentials-from-environment-variables-to-credentials-process-1df3abb33de3" rel="noopener noreferrer"&gt;this&lt;/a&gt; blog post.&lt;/p&gt;

&lt;p&gt;In your local environment, Access Keys are commonly stored in the &lt;strong&gt;~/.aws/credentials file&lt;/strong&gt; or exported as &lt;strong&gt;Environment Variables&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;As a best practice, &lt;strong&gt;~/.aws/credentials&lt;/strong&gt; should be used to contain only Access Keys, while configuration information should be specified in the &lt;strong&gt;~/.aws/config&lt;/strong&gt; file.&lt;/p&gt;

&lt;p&gt;If you’re using Environment Variables as the source of the credentials, Access Keys are exposed using the following Environment Variables: &lt;strong&gt;AWS_ACCESS_KEY_ID&lt;/strong&gt;, &lt;strong&gt;AWS_SECRET_ACCESS_KEY&lt;/strong&gt;, and - for temporary credentials - &lt;strong&gt;AWS_SESSION_TOKEN&lt;/strong&gt;.&lt;/p&gt;

&lt;h3&gt;
  
  
  What do they look like? A glance into ~/.aws/credentials file
&lt;/h3&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ybvmioc40ermltf7xdz.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3ybvmioc40ermltf7xdz.png" width="470" height="312"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you already had the opportunity to peek at the ~/.aws/credentials file, I’m quite sure you found content similar to the one illustrated in the screenshot above.&lt;/p&gt;

&lt;p&gt;Well, there is no need to explain what the &lt;strong&gt;aws_access_key_id&lt;/strong&gt;, &lt;strong&gt;aws_secret_access_key&lt;/strong&gt;, and &lt;strong&gt;aws_session_token&lt;/strong&gt; keys refer to… but there are some interesting considerations we can make about aws_access_key_id value (&lt;em&gt;ASIA2JPYALK…&lt;/em&gt;).&lt;/p&gt;

&lt;p&gt;The first four letters of the aws_access_key_id key identify the credentials type. The ASIA prefix, which you can see in the screenshot, tells us that the credentials are temporary ones, i.e. an aws_session_token is involved. These temporary credentials are generated through the AWS Security Token Service.&lt;/p&gt;

&lt;p&gt;If the aws_access_key_id starts with AKIA, it means that we’re dealing with long-term credentials; in this case, the aws_session_token is not needed.&lt;/p&gt;

&lt;p&gt;~/.aws/credentials is a &lt;em&gt;.ini&lt;/em&gt; file. In the screenshot, you can notice a &lt;strong&gt;[default]&lt;/strong&gt; header before the aws_access_key_id key. The string contained in the square brackets defines the Named Profile the Access Keys are wrapped into. The Named Profile is a container that groups &lt;em&gt;secrets and configuration information&lt;/em&gt; associated with a set of AWS credentials. As we said before, the credentials file is designed to contain only credentials; configuration information, associated with the &lt;em&gt;default&lt;/em&gt; Named Profile, should be specified in the ~/.aws/config file, under the &lt;strong&gt;[default]&lt;/strong&gt; header, as for the credentials file.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Note&lt;/strong&gt;: you can use multiple Named Profiles at the same time. The default Named Profile is the one used by clients if you don’t provide them with the Name Profile you want to use. For example, the AWS CLI will use the default Named Profile if you don’t specify the &lt;code&gt;--profile&lt;/code&gt; flag or if its value corresponds to default.&lt;/p&gt;

&lt;h2&gt;
  
  
  Stop wrestling with AWS credentials
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj0x2b0b6nnsrqxtg4cfr.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fj0x2b0b6nnsrqxtg4cfr.gif" width="480" height="362"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re wondering if there is a tool that allows you to stop thinking about AWS credentials and where to store them in the right way, give a look at &lt;a href="http://www.leapp.cloud/" rel="noopener noreferrer"&gt;Leapp&lt;/a&gt;! It takes the responsibility of storing long-term credentials in the system vault, generating/refreshing short-term credentials, and placing them in the right place for the clients to use them.&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s all Folks!
&lt;/h2&gt;

&lt;p&gt;If you’re new to AWS credentials, I hope you find this blog post a smooth introduction to them. If your curiosity is not yet satisfied, you can unwrap the &lt;a href="https://medium.com/leapp-cloud/aws-credentials-from-environment-variables-to-credentials-process-1df3abb33de3" rel="noopener noreferrer"&gt;next gift&lt;/a&gt;.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>code</category>
      <category>productivity</category>
      <category>discuss</category>
    </item>
    <item>
      <title>AWS Credentials: from Environment Variables to credentials_process</title>
      <dc:creator>Eric Villa</dc:creator>
      <pubDate>Thu, 01 Dec 2022 17:33:08 +0000</pubDate>
      <link>https://dev.to/herrvilla/aws-credentials-from-environment-variables-to-credentialsprocess-4gpn</link>
      <guid>https://dev.to/herrvilla/aws-credentials-from-environment-variables-to-credentialsprocess-4gpn</guid>
      <description>&lt;p&gt;If you need to clarify what are the different kinds of AWS Credentials available, how they’re generated, what they’re used for, and what are the best practices to manage them in a proper way, I think you landed in the right spot!&lt;/p&gt;

&lt;p&gt;Spoiler: we’re going to focus on programmatic access to AWS resources and/or services. Programmatic access means making programmatic calls to AWS via one of the available SDKs or by using the AWS Command Line Interface.&lt;/p&gt;

&lt;p&gt;First of all, let’s start from a term: Principal. For those who never heard it, let me quote the AWS Docs for you:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;A &lt;em&gt;principal&lt;/em&gt; is a person or application that can make a request for an action or operation on an AWS resource.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Every time you try to call an AWS API, you’ll meet a guardian on your way: the AWS IAM authentication, which authenticates AWS API requests.&lt;/p&gt;

&lt;p&gt;The Principal authenticates himself as a root user or as an IAM entity, i.e. an IAM User or an IAM Role. A common best practice is to avoid using root user credentials; Instead, prefer IAM entities. &lt;/p&gt;

&lt;p&gt;AWS IAM is able to authenticate API requests only if the required authentication information is present in the payload. This authentication information is represented by a signature that is added to the API request in one of the following forms: HTTP Authorization header or Query string parameters. The signature is calculated through a mechanism called AWS Signature Version 4 (SigV4), which uses the Access Keys associated with an IAM entity.&lt;/p&gt;

&lt;p&gt;So, what are Access Keys? Access keys are IAM entity-bound credentials used by clients to sign API requests for programmatic access. &lt;/p&gt;

&lt;p&gt;A client can be either the AWS CLI, AWS Tools for Windows Powershell, AWS SDKs, or an application that implements the SigV4 logic needed to add authentication information to the API requests. If you are implementing an application that interfaces with AWS resources, my suggestion is to avoid reinventing the wheel and rely on the SigV4 logic already encapsulated in the AWS SDKs, unless you have to satisfy particular needs.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Credential Provider Chain
&lt;/h2&gt;

&lt;p&gt;As I stated before, SigV4 uses Access Keys to compute the signature of an API request. Therefore, the previously described clients need to gather these credentials from somewhere, before the API request is actually signed and sent. In particular, clients follow a systematic approach to search credentials in a pre-defined set of sources. This approach is called &lt;a href="https://docs.aws.amazon.com/sdkref/latest/guide/standardized-credentials.html" rel="noopener noreferrer"&gt;Credential Provider Chain&lt;/a&gt;. The list of sources may vary depending on the specific AWS SDK, so let’s focus on the main ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;environment variables;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/sts/assume-role-with-web-identity.html" rel="noopener noreferrer"&gt;Web Identity Token credentials&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;the shared config and credentials files;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/sdkref/latest/guide/feature-container-credentials.html" rel="noopener noreferrer"&gt;Amazon ECS container credentials&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/sdkref/latest/guide/feature-imds-credentials.html" rel="noopener noreferrer"&gt;instance profile credentials&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;It is a chain in the sense that, starting from the first source in the list, the client checks for the presence of credentials; the search stops as soon as a valid set of credentials was found.&lt;/p&gt;

&lt;h2&gt;
  
  
  Long-term and temporary credentials
&lt;/h2&gt;

&lt;p&gt;Before diving into the different sources available in the Credentials Provider Chain, it is important for you to know that there are two different kinds of credentials for programmatic access: long-term and short-term (or temporary) ones. &lt;/p&gt;

&lt;p&gt;Long-term credentials consist of an access key id and a secret access key, also called access keys. You can think of the access key id as the username and the secret access key as the password. Long-term credentials allow you to access and authenticate yourself as a root user of an IAM User inside an AWS account.&lt;/p&gt;

&lt;p&gt;Short-term credentials come with two additional members: a session token together with an expiration time. Yes, because short-term credentials expire after a while, as specified in the expiration member. The main actions used to retrieve short-term credentials are the following:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/sts/assume-role.html" rel="noopener noreferrer"&gt;sts:assumeRole&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/sts/assume-role-with-saml.html" rel="noopener noreferrer"&gt;sts:assumeRoleWithSAML&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/sts/assume-role-with-web-identity.html" rel="noopener noreferrer"&gt;sts:assumeRoleWithWebIdentity&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/sts/get-federation-token.html" rel="noopener noreferrer"&gt;sts:getFederationToken&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/cli/latest/reference/sts/get-session-token.html" rel="noopener noreferrer"&gt;sts:getSessionToken&lt;/a&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://docs.aws.amazon.com/singlesignon/latest/PortalAPIReference/API_GetRoleCredentials.html" rel="noopener noreferrer"&gt;sso:getRoleCredentials&lt;/a&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Each of these actions is associated with a different access method, i.e. the pattern followed to perform a specific AWS action, in a specific AWS account, as a specific AWS IAM Entity (AWS IAM User or AWS IAM Role). We’ll focus on access methods when talking about shared config and credentials files, as these two topics are tangent.&lt;/p&gt;

&lt;p&gt;In the meanwhile, let me point out that it’s a best practice to prefer short-term credentials to long-term ones, as they limit the time window available to an attacker - who stole them - to perform malicious actions against your AWS resources.&lt;/p&gt;

&lt;p&gt;Both types of credentials can be rotated: for what concerns long-term access keys, rotating them means creating a new key pair (access key id + secret access key) associated with an IAM User and deleting the old one. On the other hand, rotating short-term credentials means creating new ones and exporting them to one of the available Credentials Provider Chain sources. To be precise, there is an exception: you don’t have to take charge of generating and rotating Amazon ECS container and instance profile credentials, as they’re sourced from an HTTP endpoint.&lt;/p&gt;

&lt;p&gt;Now that you’ve an idea of what long and short-term credentials are and what are the main differences between them, let’s dive into Credentials Provider Chain sources, starting from the environment variables, as they’re the first place clients look for credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credentials source - environment variables
&lt;/h2&gt;

&lt;p&gt;Simply put, to make a client aware of credentials as environment variables, you have to set the following ones:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;AWS_ACCESS_KEY_ID;&lt;/li&gt;
&lt;li&gt;AWS_SECRET_ACCESS_KEY;&lt;/li&gt;
&lt;li&gt;AWS_SESSION_TOKEN.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The AWS_SESSION_TOKEN environment variable should be set only for temporary credentials.&lt;/p&gt;

&lt;h2&gt;
  
  
  Credentials source - shared config and credentials file
&lt;/h2&gt;

&lt;p&gt;If the client does not find valid credentials in the previously cited environment variables, it shifts the focus to the shared config and credentials file.&lt;/p&gt;

&lt;p&gt;The shared &lt;em&gt;config&lt;/em&gt; and &lt;em&gt;credentials&lt;/em&gt; are .yml files located under the &lt;em&gt;~/.aws&lt;/em&gt; folder.&lt;/p&gt;

&lt;p&gt;Each of these files has its own purpose, even if it is not always respected. In particular, the config file is designed to keep configuration data, which is not sensitive; on the other hand, the credentials file is designed to keep secrets. These responsibilities are not respected when we find secrets in the config file and configuration data in the credentials file.&lt;/p&gt;

&lt;p&gt;When you run a command from the CLI, it is executed under the scope of a specific Named Profile. A Named Profile is a container for a specific set of configuration data and secrets. Following the best practice cited before, a Named Profile could span both config and credentials files.&lt;/p&gt;

&lt;p&gt;In the &lt;em&gt;credentials&lt;/em&gt; file, a Named Profile can wrap the following secrets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;aws_access_key_id&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;aws_secret_access_key&lt;/em&gt;;&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;aws_session_token&lt;/em&gt; (only for temporary credentials).&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the &lt;em&gt;config&lt;/em&gt; file, for each Named Profile, you can specify configuration data that allows you to describe the access method or, in simple terms, the pattern used to access services and resources in an AWS account. The AWS account the request is forwarded to depends on the IAM entity (IAM User or IAM Role) you are authenticating as.&lt;/p&gt;

&lt;h3&gt;
  
  
  The IAM User access method
&lt;/h3&gt;

&lt;p&gt;The first access method that comes through my - and maybe your - mind is the IAM User. Accessing an AWS account as an IAM User means providing at least &lt;em&gt;aws_access_key_id&lt;/em&gt; and &lt;em&gt;aws_secret_access_key&lt;/em&gt; to the &lt;em&gt;~/.aws/credentials&lt;/em&gt; file. I said “at least” because you can get temporary credentials from an IAM User too, using the &lt;em&gt;sts:getSessionToken&lt;/em&gt; action. In this case, the Named Profile - associated with the IAM User - should contain the &lt;em&gt;aws_session_token&lt;/em&gt; secret too. In this scenario, in the config file, I would put only the &lt;em&gt;region&lt;/em&gt; and &lt;em&gt;output&lt;/em&gt; fields. Please, remember to put them under the same Named Profile as the one used in the credentials file.&lt;/p&gt;

&lt;h3&gt;
  
  
  The Assume Role access method
&lt;/h3&gt;

&lt;p&gt;The second access method I want to describe is the one that expects an IAM Role to be assumed by another IAM entity. You can describe this access pattern in the shared config file using the following two Named Profile fields: &lt;em&gt;source_profile&lt;/em&gt; and &lt;em&gt;role_arn&lt;/em&gt;. &lt;/p&gt;

&lt;p&gt;The &lt;em&gt;source_profile&lt;/em&gt; corresponds to the Named Profile that wraps the configuration data and secrets associated with the &lt;em&gt;assumer&lt;/em&gt; IAM entity.&lt;/p&gt;

&lt;p&gt;The &lt;em&gt;role_arn&lt;/em&gt; corresponds to the ARN of the IAM Role that is going to be assumed. You’ve to remember to set up a trust relationship between the assumer and the assumed IAM entities, but that’s another story.&lt;/p&gt;

&lt;p&gt;Using this access method, when you run an AWS CLI command using the Named Profile associated with the assumed IAM entity, the CLI generates temporary credentials using the sts:assumeRole action and caches them for future uses under the &lt;em&gt;~/.aws/cli/cache&lt;/em&gt; folder. These cached credentials are refreshed as soon as a new AWS CLI command is run after the temporary credentials expiration time.&lt;/p&gt;

&lt;p&gt;You can even chain multiple Named Profiles using this access method.&lt;/p&gt;

&lt;p&gt;When it comes to assuming a role, it is possible to provide an additional authentication info, called external ID. The external ID is a token, shared between the AWS IAM entity and the client that wants to assume it. This token is designed to overcome the Confused Deputy problem (&lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html" rel="noopener noreferrer"&gt;https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html&lt;/a&gt;). You can specify the external ID in the Named Profile &lt;em&gt;external_id&lt;/em&gt; field under the config file.&lt;/p&gt;

&lt;p&gt;Another important configuration data that you can add to your Named Profile is the &lt;em&gt;mfa_serial&lt;/em&gt;, if associated with the IAM User that is going to assume the IAM Role.&lt;/p&gt;

&lt;p&gt;When you have to configure access to multiple AWS accounts using the Assume Role access pattern, it becomes difficult to get rid of all the Named Profiles configuration data and relationships. When you’ve to deal with a complex access scenario, tools like Leapp (&lt;a href="https://www.leapp.cloud" rel="noopener noreferrer"&gt;https://www.leapp.cloud&lt;/a&gt;) come to the rescue! Leapp avoids you to specify relationships between Named Profiles in the config file, as the access methods are stored in the tool-specific configuration file.&lt;/p&gt;

&lt;p&gt;Let’s now move to AWS SSO!&lt;/p&gt;

&lt;h3&gt;
  
  
  AWS SSO access method
&lt;/h3&gt;

&lt;p&gt;To configure access to a specific IAM Role in an AWS account by the means of AWS SSO, you’ve to provide the following configuration data in the Named Profile.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;em&gt;sso_start_url&lt;/em&gt;: the portal URL used to authenticate your client against AWS SSO (uses OIDC authentication)&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;sso_region&lt;/em&gt;: the region in which AWS SSO was configured&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;sso_account_id&lt;/em&gt;: the ID of the AWS account that I want to access&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;sso_role_name&lt;/em&gt;: the name of the role that is going to be assumed in the AWS account&lt;/li&gt;
&lt;li&gt;
&lt;em&gt;region&lt;/em&gt;: the region used by API requests&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;AWS CLI v2 supports AWS SSO and allows you to log into it through the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;aws sso login &lt;span class="nt"&gt;--profile&lt;/span&gt; &amp;lt;named-profile&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This command starts an OIDC authentication flow that requires the user to interact with the browser by providing an authorisation code and granting credentials for the AWS CLI. At this point, the CLI will receive an AWS SSO access token that is cached under the &lt;em&gt;~/.aws/sso/cache&lt;/em&gt; folder. This access token is then used by the CLI to invoke the &lt;em&gt;sso:getRoleCredentials&lt;/em&gt; action. The new set of temporary credentials is then cached under the &lt;em&gt;~/.aws/cli/cache&lt;/em&gt; folder, as for the Assume Role access method, described before.&lt;/p&gt;

&lt;p&gt;Instead of manually configuring a multitude of Named Profiles associated with different AWS SSO assumable IAM Roles, you can specify your AWS SSO configuration data in Leapp; once logged into AWS SSO, it allows you to automatically provision all the IAM Roles that you can access (you as the AWS SSO authenticated user).&lt;/p&gt;

&lt;h3&gt;
  
  
  Last but not least: the credentials_process
&lt;/h3&gt;

&lt;p&gt;&lt;em&gt;credentials_process&lt;/em&gt; is a cool feature that allows clients to generate temporary credentials by the means of a third-party CLI or command. The &lt;em&gt;credentials_process&lt;/em&gt; is a configuration data field that should be defined in the shared config file, under a specific Named Profile. Using this mechanism, you don’t have to specify credentials in other places, as the &lt;em&gt;credentials_process&lt;/em&gt; command becomes the credentials source.&lt;/p&gt;

&lt;p&gt;It is important to make the credentials_process command return the temporary credentials in the following format.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Version"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"AccessKeyId"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"an AWS access key”,
  "&lt;/span&gt;&lt;span class="err"&gt;SecretAccessKey&lt;/span&gt;&lt;span class="s2"&gt;": "&lt;/span&gt;&lt;span class="err"&gt;your&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;AWS&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;secret&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;access&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;key”&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"SessionToken"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"the AWS session token for temporary credentials”,
  "&lt;/span&gt;&lt;span class="err"&gt;Expiration&lt;/span&gt;&lt;span class="s2"&gt;": "&lt;/span&gt;&lt;span class="err"&gt;ISO&lt;/span&gt;&lt;span class="mi"&gt;8601&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;timestamp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;when&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;the&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;credentials&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;expire&lt;/span&gt;&lt;span class="s2"&gt;"
}
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;em&gt;credentials_process&lt;/em&gt; comes in handy in particular situations that are not supported out of the box by the shared configuration and credentials files. An example is the &lt;em&gt;sts:assumeRoleWithSAML&lt;/em&gt; action, which requires the user to authenticate against an external SAML IdP; once the user is authenticated, the custom script should intercept the SAML Assertion returned at the end of the SAML 2.0 authentication. Then, this SAML Assertion will be included in the &lt;em&gt;sts:assumeRoleWithSAML&lt;/em&gt; API request.&lt;/p&gt;

&lt;p&gt;Leapp allows you to configure how you want to generate credentials. By specifying “credential-process-method” in its “AWS Credential Generation” setting, you’re able to make Leapp generate temporary credentials by the means of its CLI through the &lt;em&gt;credentials_process&lt;/em&gt; field.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa59ebutfi2i562c2h8oy.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fa59ebutfi2i562c2h8oy.png" alt=" " width="800" height="453"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd7na77757n3swvgd65ey.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fd7na77757n3swvgd65ey.png" alt=" " width="800" height="89"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  That’s all Folks!
&lt;/h2&gt;

&lt;p&gt;I hope you enjoyed this article and that you found interesting tips to improve your AWS CLI configuration and credentials file management.&lt;/p&gt;

&lt;p&gt;If you want to share your thoughts about this article or, more in general, about AWS Credentials management, please reach out to me through my &lt;a href="https://twitter.com/herr_villa" rel="noopener noreferrer"&gt;Twitter profile&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;We didn’t cover every aspect of the Credentials Provider Chain, so stay tuned for new articles about credentials generation in a local or remote environment!&lt;/p&gt;

&lt;p&gt;Cheers&lt;/p&gt;

</description>
      <category>aws</category>
      <category>iam</category>
      <category>devops</category>
    </item>
    <item>
      <title>AWS is only as safe as the weakest credentials setup for your developers.</title>
      <dc:creator>Eric Villa</dc:creator>
      <pubDate>Tue, 03 May 2022 14:11:22 +0000</pubDate>
      <link>https://dev.to/herrvilla/aws-is-only-as-safe-as-the-weakest-credentials-setup-for-your-developers-38c7</link>
      <guid>https://dev.to/herrvilla/aws-is-only-as-safe-as-the-weakest-credentials-setup-for-your-developers-38c7</guid>
      <description>&lt;h2&gt;
  
  
  A matter of prevention and mitigation
&lt;/h2&gt;

&lt;p&gt;If you’re reading this article, you’re probably concerned about protecting your AWS assets from attackers, whether they’re human or machines. We will focus on how to prevent or, at least, reduce the opportunity of damage if the local cloud credentials are compromised.&lt;/p&gt;

&lt;p&gt;AWS is a public cloud provider whose services are scriptable. This means you can easily provision resources, decommission them, or perform any other action with side effects on your AWS account.&lt;/p&gt;

&lt;h2&gt;
  
  
  Requests authentication
&lt;/h2&gt;

&lt;p&gt;I refer to the action as an HTTP API call. HTTP API calls need to be signed through a process called &lt;a href="https://docs.aws.amazon.com/general/latest/gr/signature-version-4.html" rel="noopener noreferrer"&gt;Signature Version 4&lt;/a&gt;, which adds a signature to the HTTP request in a header or as a query string parameter; this allows requests to be authenticated. &lt;/p&gt;

&lt;p&gt;You can implement the Signature Version 4 process by yourself, but it is a common best practice to use existing and validated solutions, like AWS SDKs, regardless of the programming language you’re using (as long as it is supported). If you’re not implementing an application and you need access to AWS API from the command line, the AWS CLI is the way to go.&lt;/p&gt;

&lt;p&gt;AWS SDKs and AWS CLI are two examples of dev tools used to access AWS services through its authenticated API, but you can find more of them, like the AWS Toolkit for Visual Studio. All these dev tools encapsulate the SigV4 signing process described before. The signing key used to create SigV4’s signature is derived from an access key, i.e. your security credentials. If you’re dealing with short-lived security credentials, the API request contains the session token that you received from AWS STS.&lt;/p&gt;

&lt;p&gt;I’m quite sure most of you are already aware of how dev tools seek AWS Credentials locally, in your machine, but I don’t want to take it for granted.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Credentials Provider Chain
&lt;/h2&gt;

&lt;p&gt;Both AWS CLI and SDKs look for security credentials following a &lt;a href="https://docs.aws.amazon.com/sdk-for-java/v1/developer-guide/credentials.html" rel="noopener noreferrer"&gt;Credentials Provider Chain&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;From a local point of view, the main links of this chain are environment variables and shared configuration files. Basically, environment variables take precedence over the shared configuration files. If environment variables are not set, dev tools search for credentials in the $HOME/.aws/credentials file; lastly, they seek credentials in the $HOME/.aws/config file. The last one is not thought to be used as a container of sensitive information, but you can use it for this purpose. You can even use a third-party tool to generate credentials on demand by specifying the credentials_process key in the $HOME/.aws/config file.&lt;/p&gt;

&lt;h2&gt;
  
  
  Where can AWS credentials be found LOCALLY?
&lt;/h2&gt;

&lt;p&gt;It should be clear that, if someone wants to get access to our cloud assets from a compromised machine, the main targets are the environment variables and the shared configuration files, but they’re not the only ones. &lt;/p&gt;

&lt;p&gt;Based on the tools you’re using on your machine, there could be other places where an attacker can find sensitive information. For example, the attacker could find AWS credentials in one of your application’s codebases, regardless if they’re ignored by your version control tool (if you rely on git, use .gitignore file).&lt;/p&gt;

&lt;p&gt;An unnoticed yet noteworthy place where credentials could be found in the command history, accessible from both Linux and macOS machines. Imagine you exported long-term credentials as environment variables using the export command; well, this sensitive information will be kept in the history until you clear the command history.&lt;/p&gt;

&lt;p&gt;Another place where the attacker can find sensitive information that can damage not only tour AWS accounts is your password manager, whether you’re using it as a browser extension or desktop app. If the login is not expired, the malicious person (or software), can steal critical AWS credentials. For example, as a security best practice suggested by AWS, you may have stored your root account credentials in your password manager. If root account credentials are stolen, you have only one option left: contact AWS to close your account.&lt;/p&gt;

&lt;p&gt;Some local AWS credentials managers use the System Vault, e.g. macOS Keychain, to store long-term AWS credentials that are used as a baseline to generate short-term ones. The System Vault is another local asset that can be compromised by an attacker to grab AWS credentials that can be exploited to damage your AWS accounts.&lt;/p&gt;

&lt;p&gt;The ones described above are examples of the common places where an attacker can find sensitive information. You can still find them in custom places; for example, for what concerns AWS shared configuration files, you can set a custom location for both credentials and config file exporting, respectively, AWS_CONFIG_FILE and AWS_SHARED_CREDENTIALS_FILE environment variables.&lt;/p&gt;

&lt;h2&gt;
  
  
  How can your machine be compromised?
&lt;/h2&gt;

&lt;p&gt;Be careful when configuring access to your personal or work laptop. It is always recommended to use a strong password to protect it from being compromised. In the best scenario, some of your nice colleagues can introduce some funny jokes in your development environment (not that funny for you)!&lt;/p&gt;

&lt;p&gt;Another important point that is sometimes neglected consists in your disk encryption. By encrypting it, you avoid anyone to access its content unless it is unblocked with your login password.&lt;/p&gt;

&lt;p&gt;And what if I have full control of my laptop? Can something still happen? Well, as stated before, the attacker can be either a human or software. If I’m not aware of malicious software installed on my laptop, it could exploit vulnerabilities exposed by unpatched legit software. An interesting case of malicious software that is deployed with the purpose of stealing AWS Credentials is the &lt;a href="https://www.trendmicro.com/en_us/research/21/c/teamtnt-continues-attack-on-the-cloud--targets-aws-credentials.html" rel="noopener noreferrer"&gt;TeamTNT Script&lt;/a&gt;. In this case the malicious scripts are not thought to run on developer’s laptops but on AWS EC2 instances and AWS ECS containers. It steals AWS credentials via their meta-data URLs (169.254.169.254 for AWS EC2 and 169.254.170.2 for AWS ECS), as well as environment variables from Docker systems.&lt;/p&gt;

&lt;h2&gt;
  
  
  Shared Responsibility Model
&lt;/h2&gt;

&lt;p&gt;Before diving into some strategies to mitigate AWS credentials theft, let’s make a small digression on the &lt;a href="https://docs.aws.amazon.com/whitepapers/latest/introduction-devops-aws/shared-responsibility.html" rel="noopener noreferrer"&gt;Shared Responsibility Model&lt;/a&gt;. &lt;/p&gt;

&lt;p&gt;In a nutshell, AWS is responsible for the security of the cloud, not the security in the cloud. This means that AWS operates the security of hardware, software, networking, and facilities that run AWS Cloud services. On the other hand, the AWS user is responsible for selecting and configuring services and resources in the cloud, in his AWS accounts. This includes configuring Identity and Access Management following best practices. Identity and Access Management configuration affects what an IAM principal can do on what resource and under what condition. I find it useful to have a detailed overview of IAM Policy Evaluation logic because it gives an idea of the authorization flow of an authenticated HTTP API call.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp71p8ewax0zq775yp3u1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fp71p8ewax0zq775yp3u1.png" alt="Policy Evaluation flow chart" width="800" height="367"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Policy Evaluation flow chart&lt;/em&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  AWS credentials theft mitigation strategies
&lt;/h2&gt;

&lt;p&gt;Let's go through some of the best practices to reduce the opportunity of damage if the local AWS credentials are compromised.&lt;/p&gt;

&lt;h3&gt;
  
  
  1 - Do not use root account credentials
&lt;/h3&gt;

&lt;p&gt;Root account credentials should be used only during the initial AWS account set up to create an AWS IAM User with administrator privileges. Then, root account credentials should be kept safe in your password manager, e.g. LastPass or Bitwarden. Distributing root credentials is extremely dangerous as you cannot invalidate them once stolen.&lt;/p&gt;

&lt;h3&gt;
  
  
  2 - Enable MFA, everywhere!
&lt;/h3&gt;

&lt;p&gt;Whether you’re logging into AWS through a SAML federation or through IAM User credentials, enabling Multi-Factor Authentication adds a layer of security to the login process. Basically, it requires the user to specify a code in addition to the basic login information. The code can be generated either by a virtual device (e.g. Google Authenticator application) or a physical one (e.g. YubiKeys). Remember that, when using AWS role chaining feature, MFA information is carried only in case of an MFA-enabled IAM User that assumes a role that requires MFA information to be forwarded in the assumeRole API call.&lt;/p&gt;

&lt;p&gt;Passing MFA information from the AWS CLI could be cumbersome, but you can use Dev Tools like Leapp to simplify the flow.&lt;/p&gt;

&lt;p&gt;I suggest not to use MFA authenticator plugins for the browser. If you’re logged into a password manager, having an MFA authenticator plugin installed in the browser basically broke the knowledge + possession mechanism, as the second factor (the MFA code) can be retrieved from your laptop, together with the basic authentication info gained through the password manager.&lt;/p&gt;

&lt;h3&gt;
  
  
  3 - Prefer short-term credentials
&lt;/h3&gt;

&lt;p&gt;As you know, AWS allows you to sign HTTP API requests with both short-term and long-term credentials. &lt;/p&gt;

&lt;p&gt;When using long-term credentials you must be aware of the fact that, to be used by dev tools, they should be placed in one of the unencrypted locations that are part of the Credential Provider Chain. If someone stoles these credentials, they’re not limited by credentials expiration time. An example of long-term credentials is the AWS IAM User access key.&lt;/p&gt;

&lt;p&gt;On the other hand, using short-term credentials reduces the blast radius of a credentials theft. Remember that short-term credentials’ duration range varies from one access strategy to another: short-term credentials generated from an IAM User access key have a duration that ranges from 15 minutes to a maximum of 36 hours; short-term credentials generated through the assumeRoleWithSAML and assumeRole APIs have a duration that ranges from 15 minutes to a maximum of 12 hours.&lt;/p&gt;

&lt;h3&gt;
  
  
  4 - Rotate credentials
&lt;/h3&gt;

&lt;p&gt;It is a best practice to rotate credentials regularly, even if they’re short-lived ones. In this context, having a background process that refreshes them periodically makes the difference, as you don’t have to do it manually every time they expire.&lt;/p&gt;

&lt;h3&gt;
  
  
  5 - Apply the Principle of Least Privilege
&lt;/h3&gt;

&lt;p&gt;I want to point it out, even if this is not something you can do locally without accessing your AWS accounts. &lt;/p&gt;

&lt;p&gt;Credentials that are managed in your local machine always refer to an IAM Principal that has some kind of access privileges in your AWS accounts. &lt;/p&gt;

&lt;p&gt;What you can do inside these accounts depends on - at least - how access policies, resource policies, and service control policies were set (probably by someone who’s responsible for the security of your organization). That’s critical for the security of your cloud assets that every IAM Principal has a set of permissions tailored to its role inside one or more workloads. Following this best practice mitigates the damage in case of credentials theft and, in general, provides guardrails for human error-prone tasks.&lt;/p&gt;

&lt;h3&gt;
  
  
  6 - Use of the external id
&lt;/h3&gt;

&lt;blockquote&gt;
&lt;p&gt;In abstract terms, the external ID allows the user that is assuming the role to assert the circumstances in which they are operating. It also provides a way for the account owner to permit the role to be assumed only under specific circumstances. The primary function of the external ID is to address and prevent &lt;a href="https://docs.aws.amazon.com/IAM/latest/UserGuide/confused-deputy.html" rel="noopener noreferrer"&gt;The confused deputy problem&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;external id is something that must be provided by those who want to access a specific IAM Role. The only requisite is that the role has a trust policy that contains a condition with the &lt;strong&gt;sts:ExternalId&lt;/strong&gt; key. It becomes critical when trusting a third-party application as a "deputy" that can act on your behalf.&lt;/p&gt;

&lt;h3&gt;
  
  
  7 - Don’t store secrets in your source control
&lt;/h3&gt;

&lt;p&gt;When working on a project is fairly common to have one or more secrets in your project’s folder, typically for running your application locally, digitally signing your executable, launching a pipeline, connecting to your Cloud Provider, and so on.&lt;/p&gt;

&lt;p&gt;These secrets are a possible source for an attack, and there are many malevolent bots on the Internet that regularly scan public repositories like those on GitHub (they are public and accessible by everyone), or even incorrectly configured S3 buckets (wrong permissions, public access) to find secrets for exploiting accounts or services.&lt;/p&gt;

&lt;p&gt;Point is, &lt;strong&gt;always ignore secrets in your .gitignore files&lt;/strong&gt;, or even better, try to store and retrieve them programmatically from secure vaults, like your System Vault or services like AWS Secret Manager.&lt;/p&gt;

&lt;h3&gt;
  
  
  8 - Patch and upgrade your OS regularly
&lt;/h3&gt;

&lt;p&gt;It’s very important to understand that every day new exploits or vulnerabilities are found for many software or even inside OS code that can be potentially exploited to gain access to your System, retrieve sensible information, and maliciously act on your behalf. This is especially true when you are a Developer and have tools like npm installed.&lt;/p&gt;

&lt;p&gt;The more an application contains heavily used third-party libraries, the highest are the chances to be exposed to a vulnerability.&lt;/p&gt;

&lt;p&gt;To avoid being exposed to vulnerabilities, &lt;strong&gt;always strive to keep your software and OS patched and upgraded&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Keep an eye on building warnings when compiling your solution, and check your npm messages when installing a new library. Upgrade them when needed.&lt;/p&gt;

&lt;p&gt;If you are storing your project on &lt;strong&gt;GitHub verify your&lt;/strong&gt; &lt;strong&gt;DependaBot messages&lt;/strong&gt;, they usually contain precious information about vulnerabilities found in your codebase.&lt;/p&gt;

&lt;h3&gt;
  
  
  Raise the security culture of your organization
&lt;/h3&gt;

&lt;p&gt;As described in &lt;a href="https://aws.amazon.com/blogs/security/top-10-security-items-to-improve-in-your-aws-account/" rel="noopener noreferrer"&gt;this&lt;/a&gt; blog post by Nathan Case, it is critical to be involved in the dev cycle, raise your organization’s awareness of security issue, best practices, and credentials theft prevention and mitigation strategies. Moreover, it’s important to encourage the usage of standard tools to uniform and facilitate the Developer’s processes. For what concerns the local AWS credentials management, &lt;a href="https://www.leapp.cloud/index.html" rel="noopener noreferrer"&gt;Leapp&lt;/a&gt; comes to the rescue with its Desktop App and Command Line Interface. It defines a consistent way to manage your access configuration, keep sensitive information encrypted, and generate temporary credentials that can be used by Dev Tools, like the AWS CLI, to perform operations in the cloud.&lt;/p&gt;

&lt;h3&gt;
  
  
  That’s all Folks!
&lt;/h3&gt;

&lt;p&gt;I hope you find this article useful to integrate some best practices into your daily workflow, and that it has provided an opportunity to reflect on some security issues that may affect your organization. Feedback and comments are always welcome, so don’t be shy and feel free to direct message me or reach out to our &lt;a href="https://join.slack.com/t/noovolari/shared_invite/zt-opn8q98k-HDZfpJ2_2U3RdTnN~u_B~Q" rel="noopener noreferrer"&gt;Leapp Slack channel&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Keep in mind that AWS is only as safe as the weakest credentials setup for your developers.&lt;/p&gt;

</description>
      <category>devops</category>
      <category>aws</category>
      <category>security</category>
      <category>iam</category>
    </item>
    <item>
      <title>Azure access scenarios, from a DevOps point of view</title>
      <dc:creator>Eric Villa</dc:creator>
      <pubDate>Thu, 25 Mar 2021 12:58:32 +0000</pubDate>
      <link>https://dev.to/herrvilla/azure-access-scenarios-from-a-devops-point-of-view-35a2</link>
      <guid>https://dev.to/herrvilla/azure-access-scenarios-from-a-devops-point-of-view-35a2</guid>
      <description>&lt;p&gt;At a first glance, you may wonder what the "DevOps point of view" in the subtitle actually means.&lt;/p&gt;

&lt;p&gt;I used this term to describe the idea behind this article, i.e. giving you an overview of some punctual access strategies that need to be put in place to allow DevOps to access resources and services hosted inside an Azure organization.&lt;/p&gt;

&lt;p&gt;The way we design access strategies depends on different factors, e.g. the kind of operation that has to be fulfilled or the user type, whether it is internal or external to the organization.&lt;/p&gt;

&lt;p&gt;I will focus the attention on two main types of tasks: operational and development ones.&lt;/p&gt;

&lt;p&gt;By operational, I mean tasks that can be completed through the usage of the Command Line Interface or by accessing the Azure Console through a browser.&lt;/p&gt;

&lt;p&gt;On the other hand, by development tasks, I mean running scripts or testing applications locally. In this scenario, we will see that the way an application accesses Azure resources may change from development to production environment.&lt;/p&gt;

&lt;p&gt;Before describing these access scenarios, I'll take the opportunity to organize a little bit of the concepts around a complex service like Azure AD, by separating the notion of authentication from the one of authorization.&lt;/p&gt;

&lt;p&gt;In particular, we'll cover mechanisms that represent the foundation of identities authentication, regardless they're internal or external to the resource hosting Azure organization.&lt;/p&gt;

&lt;p&gt;For what concerns authorization, we'll go in-depth about Azure Role-Based Access Control, which governs who can access what resource, under what condition.&lt;/p&gt;

&lt;h1&gt;
  
  
  Summary
&lt;/h1&gt;

&lt;ul&gt;
&lt;li&gt;Azure authentication

&lt;ul&gt;
&lt;li&gt;Azure Tenant and Azure AD Directory&lt;/li&gt;
&lt;li&gt;Is the User a Member or a Guest?&lt;/li&gt;
&lt;li&gt;Federation

&lt;ul&gt;
&lt;li&gt;Custom Domain Name federation&lt;/li&gt;
&lt;li&gt;Direct Federation&lt;/li&gt;
&lt;/ul&gt;


&lt;/li&gt;

&lt;li&gt;Service Principal and Managed Service Identities&lt;/li&gt;

&lt;/ul&gt;

&lt;/li&gt;

&lt;li&gt;Azure authorization: Role-Based Access Control&lt;/li&gt;

&lt;li&gt;The "DevOps point of view": different access scenarios&lt;/li&gt;

&lt;/ul&gt;

&lt;h1&gt;
  
  
  Azure authentication
&lt;/h1&gt;

&lt;p&gt;Azure Active Directory is Azure's cloud-based access management service that stores and manages identities, enabling access to Azure resources inside a single Azure organization or across multiple ones.&lt;/p&gt;

&lt;h2&gt;
  
  
  Azure Tenant and Azure AD Directory
&lt;/h2&gt;

&lt;p&gt;When we refer to an organization, a company, or - in general terms - a domain, we use the notion of Tenant. As described in &lt;a href="https://www.herrvilla.com/how-to-saml-federate-your-azure-account-with-g-suite" rel="noopener noreferrer"&gt;my previous blog post&lt;/a&gt;, a Tenant represents "the organization that owns and manages a specific instance of Microsoft Cloud Services", i.e. a specific Tenant manages one or many Microsoft Cloud Services subscriptions, from Microsoft Office 365 to Microsoft Azure; for the sake of this article, we will focus on Azure ones.&lt;/p&gt;

&lt;p&gt;Each Tenant is associated with one and only one Directory, which represents the Azure AD service. An Azure AD Directory can manage and authenticate a pool of users that can access resources hosted in the same Tenant where the Directory lives.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is the User a Member or a Guest?
&lt;/h2&gt;

&lt;p&gt;Users stored in an Azure AD Directory can fall into one of the following categories: Member or Guest.&lt;/p&gt;

&lt;p&gt;A Member User is an identity internal to the organization, while a Guest User is an identity that has been invited to collaborate into the organisation, i.e. a partner or a collaborator.&lt;/p&gt;

&lt;p&gt;The Type is simply a property attached to a User but allows the definition and enforcement of type-based policies. &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0vhxwtg7uf7z5qhzk5sw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F0vhxwtg7uf7z5qhzk5sw.png" alt="Alt Text" width="800" height="321"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 1.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;As illustrated in Figure 1 - which is taken from Azure's Documentation - both Member and Guest Users may be homed in the organization's directory, in an external one, or even on-premise.&lt;/p&gt;

&lt;p&gt;Guest Users is the synonym of B2B User. The default B2B collaborative model expects the B2B User to be invited into the organization's directory, while it is homed in an external one. This model allows guest users to authenticate using their own organization's credentials.&lt;/p&gt;

&lt;p&gt;You can invite a User, homed in an external Azure AD Directory, as Guest User in your organization's Directory by sending an invitation email. This is not the only way to invite guest users, but it provides contextual information that allows them to accept the invite or not. To start accessing resources in your organization, a guest user needs to redeem the invitation email.&lt;/p&gt;

&lt;p&gt;If you've to import multiple guest users in your organization's directory, you can exploit the bulk invite feature, but remember that it is in preview, so don't use it in full confidence!&lt;/p&gt;

&lt;p&gt;So far, we talked about users that are internal or external to your organization, but always inside the scope of Azure AD. What if an external user belongs to an IdP that is out of Azure AD's scope? This is the situation in which federation with external identity providers comes to the rescue.&lt;/p&gt;

&lt;h2&gt;
  
  
  Federation
&lt;/h2&gt;

&lt;p&gt;Federation is the process of setting up a trust relationship between an Identity Provider and a Service Provider. In the scenario that I'm describing, Azure is the Service Provider that has to be federated with an external Identity Provider, e.g. G Suite.&lt;/p&gt;

&lt;p&gt;For what concerns Azure AD, federation with external IdPs can be established using different approaches and protocols.&lt;/p&gt;

&lt;p&gt;IMO, the two approaches that are worth exploring are Custom Domain Name federation and Direct Federation, even if the latter is still in preview.&lt;/p&gt;

&lt;h3&gt;
  
  
  Custom Domain Name federation
&lt;/h3&gt;

&lt;p&gt;This approach involves the creation of a Custom Domain Name inside your organization's Azure AD Directory. Once created and verified, you can proceed with setting up the federation between Azure AD and the external Identity Provider. This federation can rely on one of two different federation protocols: SAML 2.0 or WS-Federation. &lt;/p&gt;

&lt;p&gt;In my previous blog post I've described how to set up a SAML-based federation between Azure AD and G Suite; if you are interested in the implementation details, please refer to it.&lt;/p&gt;

&lt;p&gt;I would say this is a robust solution that allows identities, homed in an external Identity Provider, to authenticate themselves through Single Sign-On, without the necessity to create an Azure AD User or to redeem an invitation to your Azure Organization.&lt;/p&gt;

&lt;h3&gt;
  
  
  Direct Federation
&lt;/h3&gt;

&lt;p&gt;Direct Federation is another approach that enables external users to collaborate in your Azure Organization in a B2B fashion. You can set up Direct Federation only if the IdP - that external users belong to - supports SAML 2.0 or WS-Federation protocol.&lt;/p&gt;

&lt;p&gt;As for Custom Domain Name federation, you have to configure the federation both on the IdP and Azure side, as described (&lt;a href="https://docs.microsoft.com/en-us/azure/active-directory/external-identities/direct-federation" rel="noopener noreferrer"&gt;here&lt;/a&gt;).&lt;/p&gt;

&lt;p&gt;On the Azure side, you have to complete the federation set up through Azure AD's External Identities console, as illustrated in the following picture.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fons6820dkk8w0c3olz0h.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fons6820dkk8w0c3olz0h.png" alt="Alt Text" width="800" height="392"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 2.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;In this configuration, you still have to invite the external user, who has to redeem the invitation to collaborate in your Azure Organization.&lt;/p&gt;

&lt;h2&gt;
  
  
  Service Principal and Managed Service Identities
&lt;/h2&gt;

&lt;p&gt;When it comes to talking about programmatic access, Service Principal and Managed Service Identities play a crucial role. Service Principal is tight to the concept of Application in the context of Azure.&lt;/p&gt;

&lt;p&gt;Based on Azure's documentation, an Application is a template that defines "how the service can issue tokens in order to access the application, resources that the application might need to access, and the actions that the application can take". This template is used to instantiate one or more Service Principals, which are the concretization of the Application across different Tenants. When you create an Application, it comes with a default Service Principal, the "home" one.&lt;/p&gt;

&lt;p&gt;A Service Principal defines what an Application can access inside a specific Tenant.&lt;/p&gt;

&lt;p&gt;You can authenticate your automation script or software as a Service Principal through password-based or certification-based authentication. Password-based authentication requires you to provide the password that was specified during Service Principal creation. Certification-based authentication requires you to specify a certificate thumbprint that enables information retrieval from a local certificate store. Certificate-based authentication is considered a more secure solution but requires more effort to be maintained.&lt;/p&gt;

&lt;p&gt;A natural evolution of Service Principals, when running software inside an Azure Tenant, is represented by Managed Service Identities. &lt;/p&gt;

&lt;p&gt;Managed Identities avoid applications, that run on a specific virtual machine, to handle secrets. In particular, Managed Identities rely on the Azure Instance Metadata Service to retrieve temporary access tokens that are automatically rotated by Azure AD, without the need to write a logic responsible for that. Under the hood, a Managed Identity relies on a Service Principal, managed by Azure AD. A Service Principal is automatically created when we enable a Managed Identity for a virtual machine.&lt;/p&gt;

&lt;p&gt;IMO, the way Azure Managed Identities work is pretty much similar to the way AWS's Instance Profiles generate temporary credentials through the AWS Instance Metadata Service.&lt;/p&gt;

&lt;p&gt;The following picture gives a clear and complete overview of how Managed Identities mechanism works.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3bkbahnhsrakk6k4k52e.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3bkbahnhsrakk6k4k52e.png" alt="Alt Text" width="800" height="437"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 3.&lt;/strong&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  Azure authorization: Role-Based Access Control
&lt;/h1&gt;

&lt;p&gt;At this point, we've explored different Security Principals: Azure AD Users, Service Principals, and Managed Identities.&lt;/p&gt;

&lt;p&gt;We didn't talk about User Groups, as it is a concept strictly related to RBAC. Azure AD helps you assign a set of access permissions to all the members of a group, instead of having to provide the rights one-by-one. Users inherit rights defined in the Group they belong to.&lt;/p&gt;

&lt;p&gt;The Security Principal is one of the three actors involved in the Azure RBAC role assignment mechanism. The other two components involved are Role and Scope.&lt;/p&gt;

&lt;p&gt;The Security Principal is the entity that, through role assignment, receives permissions to perform actions against resources in a specific Scope. Permissions are defined inside a Role.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Scope
&lt;/h2&gt;

&lt;p&gt;The Scope is basically a resource container, that allows specifying the group of resources the Security Principal has access to.&lt;/p&gt;

&lt;p&gt;There are three types of Scopes or resources containers: Management Groups, Subscriptions, and Resource Groups.&lt;/p&gt;

&lt;p&gt;As the name suggests, Resource Groups are groups of resources that belong to the same application, workload, or project. Resource Groups are used to manage related resources' lifecycle and settings in a homogeneous way.&lt;/p&gt;

&lt;p&gt;Moving to a higher abstraction level, we find Subscriptions, which represents a way to organize and group resources that have the same billing model. You may have different Subscriptions under the same Azure Tenant.&lt;/p&gt;

&lt;p&gt;A Subscription may be the leaf of a tree called Management Group. A Management Group is used by large organizations to manage and enforce policies - even RBAC ones - to Subscriptions. A Management Group may contain other Management Groups, creating a hierarchical structure up to six levels of depth.&lt;/p&gt;

&lt;h2&gt;
  
  
  The Role
&lt;/h2&gt;

&lt;p&gt;While the Scope represents the group of resources a Security Principal can access, the Role specifies Security Principal's access rights.&lt;/p&gt;

&lt;p&gt;A Role is a definition of the subset of actions a Security Principal can perform on a Resource Provider.&lt;/p&gt;

&lt;p&gt;You may wonder what actually a Resource Provider is! Well, you can think of it as a resource supplier, which defines what management and data actions can be performed on its specific resources.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzc92dtu1qxb9h0podytn.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzc92dtu1qxb9h0podytn.png" alt="Alt Text" width="550" height="436"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 4.&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;The above picture illustrates two different kinds of Resources, Container and Blob, that are supplied by the same Resource Provider, i.e. Storage account. As you can see, there is a neat separation between Management and Data actions.&lt;/p&gt;

&lt;p&gt;Management actions allow a Security Principal to manage access to Resources and their lifecycle. On the other hand, Data actions involve the access, manipulation, and deletion of data hosted in the Resources.&lt;/p&gt;

&lt;p&gt;To give you a clear understanding of how Management and Data actions work, let me show you an example of role definition, i.e. the Storage Blob Data Reader built-in Role:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight json"&gt;&lt;code&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Name"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Storage Blob Data Reader"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Id"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"2a2b9908-6ea1-4ae2-8e65-a410df84e7d1"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"IsCustom"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="kc"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Description"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"Allows for read access to Azure Storage blob containers and data"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"Actions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Storage/storageAccounts/blobServices/containers/read"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Storage/storageAccounts/blobServices/generateUserDelegationKey/action"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"NotActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"DataActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"Microsoft.Storage/storageAccounts/blobServices/containers/blobs/read"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"NotDataActions"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[],&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="nl"&gt;"AssignableScopes"&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="w"&gt;
    &lt;/span&gt;&lt;span class="s2"&gt;"/"&lt;/span&gt;&lt;span class="w"&gt;
  &lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As specified in the description, this Role "Allows for read access to Azure Storage blob containers and data". In particular, Management actions - defined under "Actions" - allows a Security Principal to read and list Azure Storage containers; Data actions - defined under "DataActions" - allow to read and list Azure Storage blobs, that contain data.&lt;/p&gt;

&lt;p&gt;When defining actions, you can use wildcard to cover a larger subset of operations the Role allows the Security Principal to perform on Resources.&lt;/p&gt;

&lt;p&gt;NotActions and NotDataActions are arrays of strings that specify, respectively, the management and data operations that are excluded from the allowed Actions and DataActions.&lt;/p&gt;

&lt;p&gt;In this case, both Management and Data actions can be applied to all scopes: management groups, subscriptions, or resource groups. This is possible only for built-in roles that make use of the root scope "/". When you define a custom role, you can make the role available for assignment in only the management groups, subscriptions, or resource groups that require it. You must use at least one management group, subscription, or resource group.&lt;/p&gt;

&lt;p&gt;Last but not least, once you've defined the role, you can assign it to Security Principals at one of the AssignableScopes. For example, you can assign the Storage Blob Data Reader built-in Role to a Security Principal at a specific Resource Group's Scope, by creating a new role assignment from the Resource Group's IAM blade. That way, the Security Principal is allowed to perform actions based on the access rights defined in the Role definition, limited to the Resource Group's Scope.&lt;/p&gt;

&lt;h1&gt;
  
  
  The "DevOps point of view": different access scenarios
&lt;/h1&gt;

&lt;p&gt;I focused the article on access strategies that are crucial from a DevOps point of view. &lt;/p&gt;

&lt;p&gt;As I already said, access strategies have to be implemented based on the kind of task the person, or - using Azure terminology - the Security Principal, has to do.&lt;/p&gt;

&lt;p&gt;Let's go back to the distinction between Operational and Development tasks.&lt;/p&gt;

&lt;p&gt;Now that we have a better knowledge of different access strategies and approaches, it should be clear that Guest User invitation and Federation with external Identity Providers enables DevOps to perform tasks that fall into the Operational category. For what concerns Federation, there are plenty of different Identity Providers that you can federate with your Organization's Azure AD Directory, even on-premises ones. Please, refer to online guides - giving priority to the ones provided by Azure - to get more details about your IdP-specific federation setup.&lt;/p&gt;

&lt;p&gt;As I said before, when it comes to enable programmatic access by your automation scripts and/or applications, Service Principals and Managed Identities are fundamental. We have already covered differences between these two actors, but let me make some considerations about the environment in which code is executed.&lt;/p&gt;

&lt;p&gt;If I - as a developer - need to run my application or automation scripts locally, one of the possible ways to let them access Azure Resources is by using Service Principals. If I'm developing the application using the Azure SDK, the Service Principal should be created with the following command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;az ad sp create-for-rbac &lt;span class="nt"&gt;--sdk-auth&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The newly created Service Principal information follows a standard JSON format, which contains a ClientId and a ClientSecret, among other properties. You can use this JSON to authenticate with token credentials or perform file-based authentication.&lt;/p&gt;

&lt;p&gt;That said, this is not the best practice for production applications to retrieve temporary credentials. The de facto standard in that sense is represented by Managed Identities that, as I explained before, rely on the Azure Instance Metadata Service to generate and auto-rotate short-term credentials associated with a managed Service Principal.&lt;/p&gt;

&lt;p&gt;The following Python code snippet gives you an idea of how it is simple to instantiate Managed Identity credentials using Azure SDK.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight python"&gt;&lt;code&gt;&lt;span class="kn"&gt;from&lt;/span&gt; &lt;span class="n"&gt;msrestazure.azure_active_directory&lt;/span&gt; &lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="n"&gt;MSIAuthentication&lt;/span&gt;

&lt;span class="n"&gt;credentials&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;MSIAuthentication&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  That's all, folks!
&lt;/h1&gt;

&lt;p&gt;I hope you find this blog post interesting and useful. We covered many different Azure AD authentication and authorization aspects, tailored to a DevOps point of view. I've shared some of my knowledge with you. Now it's your turn! I'll really appreciate your feedback and, most of all, real-world examples that allow me to improve the article's quality.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>devops</category>
      <category>security</category>
      <category>opensource</category>
    </item>
    <item>
      <title>New AWS EC2 Mac Instances: a CI/CD test bench</title>
      <dc:creator>Eric Villa</dc:creator>
      <pubDate>Fri, 08 Jan 2021 12:26:45 +0000</pubDate>
      <link>https://dev.to/herrvilla/new-aws-ec2-mac-instances-a-ci-cd-test-bench-29c3</link>
      <guid>https://dev.to/herrvilla/new-aws-ec2-mac-instances-a-ci-cd-test-bench-29c3</guid>
      <description>&lt;p&gt;During the last AWS re:Invent, AWS made one of the most discussed announcement, that — on paper —  opens a lot of new scenarios: AWS EC2 Mac Instances! &lt;/p&gt;

&lt;p&gt;Don't worry, we will deepen one of these scenarios later on in this blog post, but let's first introduce this new instance type.&lt;/p&gt;

&lt;p&gt;Amazon EC2 Mac Instances come with an 80s name, which makes them more attractive to those of you who are a little bit older than me 🙂. They're called mac1.metal instances.&lt;/p&gt;

&lt;p&gt;Talking about hardware, Amazon EC2 Mac Instances are backed by Mac mini hosts, that rely on AWS Nitro controllers to connect with AWS network infrastructure and services. The interesting point is that Mac Instances are connected to the Nitro System through the Thunderbolt 3 interface. I used the term "host" to highlight the fact that we're not dealing with Virtual Machines, but with Dedicated Hosts; whenever I decide to run an Amazon EC2 Mac Instance, AWS provisions a concrete Mac mini host for my purposes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdt3nq418n0djmoisx91q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fdt3nq418n0djmoisx91q.png" alt="Alt Text" width="800" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;em&gt;Peter Desantis, Senior Vice President of AWS Infrastructure and Support, presenting new Amazon EC2 Mac Instances at AWS re:Invent 2020 Infrastructure Keynote.&lt;/em&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  mac1.metal — the specs
&lt;/h1&gt;

&lt;p&gt;At this point — assuming that you never heard about Amazon EC2 Mac Instances hardware specifications — you may wonder what are the supported sizes. Well, as far as now, you can forget the word "choice": AWS allows you to run only one size of Mac Instances. mac1.metal instances' hardware specifications tell us that they're powered by an Intel Coffee Lake processor running at 3.2 GHz — that can burst up to 4.6 GHz — and 32 GiB of memory. As explained by Jeff Barr in the AWS News Blog, instances run in a VPC, include ENA networking, and are natively Optimized for communication with EBS volumes, supporting I/O intensive workloads.&lt;/p&gt;

&lt;p&gt;In my daily routine, my working partner is a macOS laptop that I had to update to the new macOS Big Sur operating system. So far it didn't bring me tangible enhancements, but it's quite a best-practice to keep your system up to date, at least on your workstation. AWS EC2 Mac Instances come with a limitation in that sense: only Mojave or Catalina macOS versions can be selected. Mojave and Catalina AMIs comes with the AWS CLI, Command Line Tools for Xcode, Homebrew, and SSM Agent already installed. AWS is working to add support for Big Sur, and for Apple M1 Chip.&lt;/p&gt;

&lt;h1&gt;
  
  
  A practical Use Case
&lt;/h1&gt;

&lt;p&gt;Now, let's focus on what I like the most: practical use cases!&lt;/p&gt;

&lt;p&gt;I started my career as a developer, and I guess every developer's mind made — at least — an association between this announcement and the possibility to automate building, testing, and signing of macOS and iOS applications.&lt;/p&gt;

&lt;p&gt;During the last year, my team has been developing an Open-Source Desktop Application that manages local credentials to access complex Cloud Environments. Our application is written in TypeScript, interpreted by Node.js. We used Angular as our development framework, which runs on top of an Electron engine for cross-platform compatibility.&lt;/p&gt;

&lt;p&gt;Electron comes with a native application builder, called electron-builder, that we used to write custom build scripts in our package.json file, which contains dependencies specifications too. We wrote custom scripts to build Linux, Windows, and macOS binaries.&lt;/p&gt;

&lt;p&gt;In order to build the macOS binary, the script needs to have access to the Signing Certificate and to the Apple Notarisation Password. They allow, respectively, to sign and notarize the macOS binary. We usually store these secrets in our macOS Keychain, run the build scripts on our local environments, and manually upload the artifacts on our GitHub repository as a new release. This is a common practice adopted by many developers when building macOS or iOS applications.&lt;/p&gt;

&lt;p&gt;This process is slow, cumbersome, and may lead to human errors. But hey, there seems to be a new opportunity out there for us. What better Use Case for the new Amazon EC2 Mac Instances than building our application's macOS binary?&lt;/p&gt;

&lt;p&gt;It's time to focus on how I set up the test bench. We will go through the following steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;launch of a blend new mac1.metal instance;&lt;/li&gt;
&lt;li&gt;access to the instance;&lt;/li&gt;
&lt;li&gt;installation of packages and tools needed during the build process;&lt;/li&gt;
&lt;li&gt;configuration of the build pipeline with the dear old Jenkins.&lt;/li&gt;
&lt;/ul&gt;

&lt;h1&gt;
  
  
  Launch a mac1.metal instance
&lt;/h1&gt;

&lt;p&gt;The first thing we've to do to get our pipeline set up consists of the creation of the Amazon EC2 Mac Instance on which we're going to install and configure Jenkins.&lt;/p&gt;

&lt;p&gt;Let's jump into the AWS console!&lt;/p&gt;

&lt;p&gt;As for any other EC2 instance, the launch wizard of a mac1.metal kicks off from EC2 console, in the "Instances" section. As many of you already know, here you can find the list of EC2 instances available and — among the others — the menu needed to launch a new instance.&lt;/p&gt;

&lt;p&gt;Since the 30 November 2020, the AMI list is richer: indeed, it shows both Mojave and Catalina AMIs; for our purposes, I choose Catalina.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvmek8npz0et3j0eahcd1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fvmek8npz0et3j0eahcd1.png" alt="Alt Text" width="800" height="249"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When it comes to choosing the instance type, there is only one available, called mac1.metal. As we already know, it is characterized by 12 vCPUs running at 3.2GHz and 32GiB of memory. If you think of it as your workstation it does not sound that weird!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4y5cmw3wm2s2f99y9zp4.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F4y5cmw3wm2s2f99y9zp4.png" alt="Alt Text" width="800" height="186"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;In the rest of the wizard, we can treat our Mac Instance like any other instance type; the only thing that we should take particular attention to is the tenancy. We're going to launch the instance on a Dedicated Host that we can request — on a separate tab — during the instance creation process. Even for the Dedicated Host, we've to specify mac1.metal as the type of instances that can be launched on it.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fa4i7r00imkgoesvg5oqa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fa4i7r00imkgoesvg5oqa.png" alt="Alt Text" width="800" height="640"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;For the sake of this proof of concept, I decided to run the instance in a public subnet, and enable Public IP auto-assignment.&lt;/p&gt;

&lt;p&gt;To allow the installation of the heavy-weight Xcode — which provides some critical build tools — attach an EBS root volume with an appropriate size to the instance; in my case, I choose to attach a 100GiB-sized EBS volume.&lt;/p&gt;

&lt;h1&gt;
  
  
  What about access types?
&lt;/h1&gt;

&lt;p&gt;Before diving into Mac Instance access types, remember to setup Security Group rules that allow you to reach it through SSH and VNC. Moreover, I configured a rule to allow access through my browser to port 8080 of the instance, i.e. the one associated with the Jenkins service. Since I decided to run the instance in a public subnet, I restricted access to the instance only to my IP address.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DISCLAIMER:&lt;/strong&gt; it works, but please note that the setup I used — in terms of networking — cannot be considered production-ready! To make it more secure, it is enough to move the Mac Instance inside a private subnet, and place an OpenVPN server in the public subnet; that way, the mac1.metal instance is no more exposed directly to the internet and we can access it by the means of the OpenVPN server.&lt;/p&gt;

&lt;p&gt;In the last step of the instance creation wizard, we've to choose whether to select an existing .pem key or to create a new one to access the instance via SSH. That's the first access type available, and it's no different from SSH access to an Amazon Linux instance; indeed, the username for Mac Instances is ec2-user.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmem8bwqvmmoq5pffvdpi.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fmem8bwqvmmoq5pffvdpi.png" alt="Alt Text" width="800" height="228"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you need a graphical access to the instance — which will be needed while installing packages and tools — you can use VNC; if you're a macOS user, you can rely on VNC Viewer software to setup the connection to your mac1.metal instance.&lt;/p&gt;

&lt;p&gt;But wait — as AWS Technical Evangelist &lt;a href="https://twitter.com/sebsto" rel="noopener noreferrer"&gt;Sébastien Stormacq&lt;/a&gt; explains in &lt;a href="https://www.youtube.com/watch?v=FtU2_bBfSgM&amp;amp;ab_channel=freeCodeCamp.org" rel="noopener noreferrer"&gt;this&lt;/a&gt; video — there is something you've to configure on the instance before having the possibility to access it. In particular, you've to set a password for the ec2-user, and enable the VNC server. Here is the GitHub Gist I've followed, and that is very precious to me:&lt;/p&gt;


&lt;div class="ltag_gist-liquid-tag"&gt;
  
&lt;/div&gt;


&lt;p&gt;&lt;strong&gt;NOTE:&lt;/strong&gt; 45-49 lines are critical in the sense that, without them, you'll not be able to install Xcode; the initial APFS container size is not large enough to accommodate Xcode.&lt;/p&gt;

&lt;p&gt;And that's all for what concerns access types.&lt;/p&gt;

&lt;h1&gt;
  
  
  Let's install some packages and tools
&lt;/h1&gt;

&lt;p&gt;The build pipeline that we are going to configure comes with some prerequisites that we've to satisfy. So, what are these prerequisites?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A Java installation&lt;/li&gt;
&lt;li&gt;Xcode Application, because default Command Line Tools do not provide altool, which is needed to notarise the app.&lt;/li&gt;
&lt;li&gt;The actual Jenkins service&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Where possible, I relied on brew to install packages. In particular, I've used it to install Java and Jenkins; then, I've installed Xcode from the App Store, providing my Apple Credentials.&lt;/p&gt;

&lt;p&gt;Install Xcode first, the process is straightforward: open the App Store, search for Xcode, and install it.&lt;/p&gt;

&lt;p&gt;Now, let's focus on Java. I choose Java AdoptOpenJDK 11 version, which can be installed using brew in this way:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Update brew first of all&lt;/span&gt;
brew update

&lt;span class="c"&gt;# Add adoptopenjdk/openjdk repository&lt;/span&gt;
brew tap adoptopenjdk/openjdk

&lt;span class="c"&gt;# Install Java AdoptOpenJDK 11&lt;/span&gt;
brew &lt;span class="nb"&gt;install&lt;/span&gt; &lt;span class="nt"&gt;--cask&lt;/span&gt; adoptopenjdk11
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;To install Jenkins, I've used the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew &lt;span class="nb"&gt;install &lt;/span&gt;jenkins-lts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once installed, we've to make Jenkins accessible from outside by modifying the /usr/local/opt/jenkins-lts/homebrew.mxcl.jenkins-lts.plist file. In particular, we've to change the --httpListenAddress option from 127.0.0.1 to 0.0.0.0. Then, simply start the service using the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;brew services start jenkins-lts
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;h1&gt;
  
  
  Jenkins initial configuration
&lt;/h1&gt;

&lt;p&gt;Jenkins's initial configuration involves three steps:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;unlock Jenkins — in this step, we've to retrieve the password that was written inside the /Users/ec2-user/.jenkins/secrets/initialAdminPassword file;&lt;/li&gt;
&lt;li&gt;install plugins — in addition to the pre-selected ones, check NodeJS, Git Parameter, and GitHub plugins;&lt;/li&gt;
&lt;li&gt;create admin user — finally, create the admin user, providing credentials, full name, and email address.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  Credentials &amp;amp; Secrets
&lt;/h2&gt;

&lt;p&gt;Before focusing on the build job, let's create all the credentials and secrets needed to pull the code from the repo, sign the binary, notarize it, and finally push the artifacts back to the GitHub repo as a new release draft.&lt;/p&gt;

&lt;p&gt;So, what are the credentials and secrets needed by the build job?&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;GitHub personal access token&lt;/li&gt;
&lt;li&gt;Apple signing certificate (in base64 format)&lt;/li&gt;
&lt;li&gt;Apple notarisation password&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I set them as global secrets from /credentials/store/system/. Here, add credentials and secrets respecting these types:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0jljrzhbz7xe2fhf3nc1.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0jljrzhbz7xe2fhf3nc1.png" alt="Alt Text" width="800" height="320"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;The GitHub personal access token 2 secret is different from the first one, in the sense that it is used to push the artifacts back to the GitHub repo, while the first one is used to pull the code from the repo.&lt;/p&gt;

&lt;h1&gt;
  
  
  Build Job configuration
&lt;/h1&gt;

&lt;p&gt;We can start the Build Job configuration wizard by clicking "New Item" from the sidebar on the left of the Dashboard. For what concerns this wizard, we'll go into the details of Source Code Management, Build Triggers, Build Environment Bindings, and Build sections.&lt;/p&gt;

&lt;p&gt;In the Source Code Management section, we've to specify the coordinates of our GitHub repository, providing access credentials, repo URL, and the branch from which Jenkins will pull the code from.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnj81iw1ht3v2osvl7cyo.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnj81iw1ht3v2osvl7cyo.png" alt="Alt Text" width="800" height="380"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I've decided to make Jenkins check for newly available commits every 5 minutes, in a polling fashion; the alternative consists of setting up a Jenkins webhook invoked directly by GitHub, in a push fashion.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnu8pyljmc708hkfxvool.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fnu8pyljmc708hkfxvool.png" alt="Alt Text" width="800" height="278"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Next step: Environment Variables, which I referred to as Build Environment Bindings. Here we have simply to assign the previously configured credentials and secrets to environment variables used in the Build Job's steps.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0qoxy59l2v6ebbhm2ep3.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2F0qoxy59l2v6ebbhm2ep3.png" alt="Alt Text" width="800" height="416"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;And finally, let's add the build steps! I divided the build in five steps, i.e. five Execute shell commands, which I want to illustrate down here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# Step 1&lt;/span&gt;
&lt;span class="nb"&gt;chmod&lt;/span&gt; +x ./scripts/add-osx-cert.sh

&lt;span class="c"&gt;# Step 2&lt;/span&gt;
./scripts/add-osx-cert.sh

&lt;span class="c"&gt;# Step 3&lt;/span&gt;
npm &lt;span class="nb"&gt;install&lt;/span&gt;

&lt;span class="c"&gt;# Step 4&lt;/span&gt;
npm run rebuild-keytar

&lt;span class="c"&gt;# Step 5&lt;/span&gt;
npm run dist-mac-prod
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Apart from step 3 and step 4, you may wonder what add-osx-cert.sh and dist-mac-prod scripts consist of. Therefore, I want to provide you their implementation.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;project-root-folder/scripts/add-osx-cert.sh&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;#!/usr/bin/env sh&lt;/span&gt;

&lt;span class="nv"&gt;KEY_CHAIN&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;build.keychain
&lt;span class="nv"&gt;CERTIFICATE_P12&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;certificate.p12

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"Recreate the certificate from the secure environment variable"&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="nv"&gt;$CERTIFICATE_OSX_P12&lt;/span&gt; | &lt;span class="nb"&gt;base64&lt;/span&gt; &lt;span class="nt"&gt;--decode&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nv"&gt;$CERTIFICATE_P12&lt;/span&gt;

&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"security create-keychain"&lt;/span&gt;
security create-keychain &lt;span class="nt"&gt;-p&lt;/span&gt; jenkins &lt;span class="nv"&gt;$KEY_CHAIN&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"security list-keychains"&lt;/span&gt;
security list-keychains &lt;span class="nt"&gt;-s&lt;/span&gt; login.keychain build.keychain
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"security default-keychain"&lt;/span&gt;
security default-keychain &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nv"&gt;$KEY_CHAIN&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"security unlock-keychain"&lt;/span&gt;
security unlock-keychain &lt;span class="nt"&gt;-p&lt;/span&gt; jenkins &lt;span class="nv"&gt;$KEY_CHAIN&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"security import"&lt;/span&gt;
security import &lt;span class="nv"&gt;$CERTIFICATE_P12&lt;/span&gt; &lt;span class="nt"&gt;-k&lt;/span&gt; &lt;span class="nv"&gt;$KEY_CHAIN&lt;/span&gt; &lt;span class="nt"&gt;-P&lt;/span&gt; &lt;span class="s2"&gt;""&lt;/span&gt; &lt;span class="nt"&gt;-T&lt;/span&gt; /usr/bin/codesign&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"security find-identity"&lt;/span&gt;
security find-identity &lt;span class="nt"&gt;-v&lt;/span&gt;
&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s2"&gt;"security set-key-partition-list"&lt;/span&gt;
security set-key-partition-list &lt;span class="nt"&gt;-S&lt;/span&gt; apple-tool:,apple:,codesign:, &lt;span class="nt"&gt;-s&lt;/span&gt; &lt;span class="nt"&gt;-k&lt;/span&gt; jenkins &lt;span class="nv"&gt;$KEY_CHAIN&lt;/span&gt;

&lt;span class="c"&gt;# Remove certs&lt;/span&gt;
&lt;span class="nb"&gt;rm&lt;/span&gt; &lt;span class="nt"&gt;-fr&lt;/span&gt; &lt;span class="k"&gt;*&lt;/span&gt;.p12
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;dist-mac-prod — custom script which has to be added in the script section of the package.json file&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="s2"&gt;"dist-mac-prod"&lt;/span&gt;: &lt;span class="s2"&gt;"rm -rf electron/dist &amp;amp;&amp;amp; rm -rf release &amp;amp;&amp;amp; rm -rf dist &amp;amp;&amp;amp; tsc --p electron &amp;amp;&amp;amp; ng build --aot --configuration production --base-href ./ &amp;amp;&amp;amp; mkdir -p electron/dist/electron/assets/images &amp;amp;&amp;amp; cp -a electron/assets/images/* electron/dist/electron/assets/images/ &amp;amp;&amp;amp; electron-builder build --publish=onTag"&lt;/span&gt;,
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;For the sake of this article, the important part of the dist-mac-prod script is&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;electron-builder build &lt;span class="nt"&gt;--publish&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;onTag
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;which triggers the build of the binary.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Inside the package.json file, there is another important part that we've to specify, and that is included in the "build" section; let's show that down here.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="c"&gt;# ...&lt;/span&gt;
&lt;span class="s2"&gt;"build"&lt;/span&gt;: &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="s2"&gt;"publish"&lt;/span&gt;: &lt;span class="o"&gt;[&lt;/span&gt;
            &lt;span class="o"&gt;{&lt;/span&gt;
                &lt;span class="s2"&gt;"provider"&lt;/span&gt;: &lt;span class="s2"&gt;"github"&lt;/span&gt;,
                &lt;span class="s2"&gt;"owner"&lt;/span&gt;: &lt;span class="s2"&gt;"ericvilla"&lt;/span&gt;,
                &lt;span class="s2"&gt;"repo"&lt;/span&gt;: &lt;span class="s2"&gt;"leapp"&lt;/span&gt;,
                &lt;span class="s2"&gt;"releaseType"&lt;/span&gt;: &lt;span class="s2"&gt;"draft"&lt;/span&gt;
            &lt;span class="o"&gt;}&lt;/span&gt;
        &lt;span class="o"&gt;]&lt;/span&gt;,
        &lt;span class="s2"&gt;"afterSign"&lt;/span&gt;: &lt;span class="s2"&gt;"scripts/notarize.js"&lt;/span&gt;,
&lt;span class="c"&gt;# ...&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As you can see, I'm requesting to push the artifact to the ericvilla/leapp repo — which is a fork of &lt;a href="https://github.com/Noovolari/leapp" rel="noopener noreferrer"&gt;https://github.com/Noovolari/leapp&lt;/a&gt; — as a new DRAFT release.&lt;/p&gt;

&lt;p&gt;Moreover, I specified to run the script/notarize.js script after signing. This script is responsible for macOS application notarisation, and is implemented as follows:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight jsx"&gt;&lt;code&gt;&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;notarize&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;require&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;electron-notarize&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

&lt;span class="nx"&gt;exports&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="k"&gt;default&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;async&lt;/span&gt; &lt;span class="kd"&gt;function&lt;/span&gt; &lt;span class="nf"&gt;notarizing&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;electronPlatformName&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;appOutDir&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;electronPlatformName&lt;/span&gt; &lt;span class="o"&gt;!==&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;darwin&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;appName&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;packager&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;appInfo&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;productFilename&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="k"&gt;await&lt;/span&gt; &lt;span class="nf"&gt;notarize&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt;
    &lt;span class="na"&gt;appBundleId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="s1"&gt;com.noovolari.leapp&lt;/span&gt;&lt;span class="dl"&gt;'&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;appPath&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;`&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;appOutDir&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;/&lt;/span&gt;&lt;span class="p"&gt;${&lt;/span&gt;&lt;span class="nx"&gt;appName&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="s2"&gt;.app`&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;appleId&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;mobile@besharp.it&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
    &lt;span class="na"&gt;appleIdPassword&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;APPLE_NOTARISATION_PASSWORD&lt;/span&gt; &lt;span class="p"&gt;?&lt;/span&gt; &lt;span class="nx"&gt;process&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;env&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;APPLE_NOTARISATION_PASSWORD&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt;
      &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;@keychain:Leapp&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
  &lt;span class="p"&gt;});&lt;/span&gt;
&lt;span class="p"&gt;};&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It relies on electron-notarize package and looks for APPLE_NOTARISATION_PASSWORD environment variable; if it is not available, it assumes you're running the build in your local environment. Therefore, it looks for appleIdPassword inside the System's Keychain.&lt;/p&gt;

&lt;p&gt;Last but not least, I had to install a Node.js version from inside Jenkins in order to build the solution correctly. To do that, move to the "Manage Jenkins" section, accessible from the left sidebar. Once inside it, click "Global Tool Configuration"; there you can install the Node.js version you need. In my case, I've installed Node.js 12.9.1 version.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgescjwsisty12qvp6ous.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fi%2Fgescjwsisty12qvp6ous.png" alt="Alt Text" width="800" height="562"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here we are, at the end of the Build Job configuration!&lt;/p&gt;

&lt;p&gt;If Jenkins service is running and the Build Job is set up, it checks for new pushes on the GitHub repo, and triggers the build process.&lt;/p&gt;

&lt;p&gt;If everything worked fine, you'll be able to find the newly created Release Draft under &lt;a href="https://github.com/" rel="noopener noreferrer"&gt;https://github.com/&lt;/a&gt;//releases path.&lt;/p&gt;

&lt;h1&gt;
  
  
  Let's Sum Up
&lt;/h1&gt;

&lt;p&gt;And now, it's time to make some considerations!&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foyhety0lzoqx21dt4ln7.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Foyhety0lzoqx21dt4ln7.gif" alt="https://media.giphy.com/media/Hm3ZMI68o17os/giphy.gif" width="320" height="193"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;When reading this blog post everything seems to be clear and straightforward (well, I hope that to be so 🙂), but during my first set up I got in trouble many times, and I want to highlight that here.&lt;/p&gt;

&lt;p&gt;First of all, do you know that in order to run a Mac Instance you've to allocate a Dedicated Host for at least 24 hours? Maybe yes. But, in the context of this use case, it is critical to have the possibility to run build jobs only when needed; you may argue "ok, but you set up Jenkins to check for new commits in a polling fashion", and I would say you're right. Indeed, we usually rely on container-based services like AWS CodeBuild to run build environments, let's say, on-demand. It may be more convenient to run the build manually in your local environment, or automatically by setting up Jenkins as we did, but on your local machine.&lt;/p&gt;

&lt;p&gt;Why I'm saying that?&lt;/p&gt;

&lt;p&gt;Simple. A Mac Instance Dedicated Host is not cheap: it costs $1.083 per hour, which means almost $26 fixed costs whenever I decide to run a new one (Dedicated Host allocated for at least 24 hours). Due to the Dedicated Host minimum allocation time limitation, IMO it is not possible — at least very difficult — to set up cost savings strategies, like running the CI/CD instance only during working hours, e.g. 8 hours per day.&lt;/p&gt;

&lt;p&gt;That's not all.&lt;/p&gt;

&lt;p&gt;If you decide to run a Mac Instance, you've to take into account the fact that sometimes EC2 instance Health Checks do not pass; that means — for EBS-backed AMIs — that you need to stop the instance, wait until the Dedicated Host exits the pending status, and finally restart the instance. What does it mean? A lot of wasted time.&lt;/p&gt;

&lt;p&gt;I'm using what may sound like a polemic tone, but constructively. I think that's a great announcement, and that this service has a lot of potentials. Yes, potential, because I felt it is a little bit immature yet.&lt;/p&gt;

&lt;p&gt;Apart from these considerations, the process of setting up a pipeline with Jenkins is exactly the same as in my local environment, and the different ways we have to access the Mac Instance grants us a complete experience.&lt;/p&gt;

&lt;h1&gt;
  
  
  That's all folks!
&lt;/h1&gt;

&lt;p&gt;Here we are.&lt;/p&gt;

&lt;p&gt;My thanks go to every member of my team, in particular to &lt;a href="https://twitter.com/Balubor" rel="noopener noreferrer"&gt;Alessandro Gaggia&lt;/a&gt;, who helped me getting out of troubles, and who gave me moral and technical support during Jenkins setup.&lt;/p&gt;

&lt;p&gt;I hope you find this blog post useful, and that lots of questions and ideas raised in your minds. In that case, please do not hesitate to contact me; it will be a pleasure to share considerations about this or other use-cases.&lt;/p&gt;

&lt;p&gt;Stay tuned for new articles!&lt;/p&gt;

</description>
      <category>aws</category>
      <category>ec2</category>
      <category>macos</category>
      <category>electron</category>
    </item>
    <item>
      <title>How to SAML federate your Azure account with G Suite</title>
      <dc:creator>Eric Villa</dc:creator>
      <pubDate>Wed, 28 Oct 2020 14:21:54 +0000</pubDate>
      <link>https://dev.to/herrvilla/how-to-saml-federate-your-azure-account-with-g-suite-10hj</link>
      <guid>https://dev.to/herrvilla/how-to-saml-federate-your-azure-account-with-g-suite-10hj</guid>
      <description>&lt;h1&gt;
  
  
  Why should I use an external Identity Provider?
&lt;/h1&gt;

&lt;p&gt;One of the most seen patterns in talking about Cloud Access Management consists of adopting an external Identity Provider to store, manage, and authenticate your corporate identities that need to access resources in multiple Cloud Providers.&lt;/p&gt;

&lt;p&gt;Enabling Access to those resources involves setting up a federation between your Cloud Accounts and your Identity Provider.&lt;/p&gt;

&lt;p&gt;In the previous blog post, we described how to set up a federation between G Suite, as the Identity Provider, and AWS, as the Service Provider. Here we will shift the focus on the federation process between G Suite and Azure.&lt;/p&gt;

&lt;p&gt;If you come from the Azure world, you have probably used - or at least seen - Azure AD as your Identity Provider to access resources contained in your Azure accounts; it is relatively straightforward. &lt;/p&gt;

&lt;p&gt;But what if you are new to Azure and want to make it accessible by your G Suite users without migrating them to Azure AD or another Identity Provider?&lt;/p&gt;

&lt;p&gt;Read on, you're in the right place! &lt;/p&gt;

&lt;p&gt;We are showing you the path to a convenient and maintainable solution for delegating corporate identity management and authentication to an already set up Identity Provider.&lt;/p&gt;

&lt;h1&gt;
  
  
  Use case: Access Azure accounts through the Azure CLI
&lt;/h1&gt;

&lt;p&gt;Let's assume a real-world use case: &lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Framn8pydsspa8xdge34q.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Framn8pydsspa8xdge34q.png" alt="1.png" width="631" height="623"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 1:&lt;/strong&gt; Federated Single Sign-On that involves G Suite ad IdP and Azure as SP.&lt;/p&gt;

&lt;p&gt;This scenario shows a G Suite user - or identity - logging into Azure through the Azure CLI's &lt;code&gt;az login&lt;/code&gt; command.&lt;/p&gt;

&lt;p&gt;As you can see, to allow G Suite identities to access Azure, it is necessary to Federate the G Suite &lt;a href="https://support.google.com/a/answer/4352075?hl=en" rel="noopener noreferrer"&gt;Organisational Unit&lt;/a&gt; with the Azure AD Domain; we will see later in this article how to implement it.&lt;/p&gt;

&lt;p&gt;Keep in mind that Azure AD remains Azure's entry point even if it doesn't act as Identity Provider. Azure AD delegates the authentication process to G Suite.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;strong&gt;Role-Based Access Control for Azure resources&lt;/strong&gt;
&lt;/h1&gt;

&lt;p&gt;Once a user has authenticated against the Identity Provider, he can access resources in different Azure Subscriptions based on his assigned roles. This kind of Access is called Role-Based Access Control or RBAC.&lt;/p&gt;

&lt;p&gt;To better understand how RBAC works, we start presenting the main actors involved.&lt;/p&gt;

&lt;p&gt;The first one we will focus on is the &lt;strong&gt;Tenant&lt;/strong&gt;. It represents "the organization that owns and manages a specific instance of Microsoft Cloud Services," i.e. a specific Tenant manages one or many Microsoft Cloud Services subscriptions, from Microsoft Office 365 to Microsoft Azure.&lt;/p&gt;

&lt;p&gt;Each Tenant is associated with one and only one &lt;strong&gt;Directory&lt;/strong&gt;, which represents the Azure AD service.&lt;/p&gt;

&lt;p&gt;In its default configuration, the Azure AD Directory is responsible for managing and authenticating a user pool. As stated before, in this configuration, the Identity Provider is an external one, i.e. G Suite.&lt;/p&gt;

&lt;p&gt;We can associate a directory to one or many Subscriptions; users' Role-Based Access to these Subscriptions is controlled through Azure Identity and Access Management (IAM) service.&lt;/p&gt;

&lt;p&gt;We can control Role-Based Access at four different levels:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Management Groups&lt;/strong&gt; - help you manage your Azure subscriptions by grouping them;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Subscriptions&lt;/strong&gt; - help you organize access to Azure resources and determine how resource usage is reported, billed, and paid for;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resource Groups&lt;/strong&gt; - containers that hold related resources for an Azure solution;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Resources&lt;/strong&gt; - Cloud Resources, e.g., Virtual Machines, Databases.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66bp8q4h1eyztiwk7awp.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F66bp8q4h1eyztiwk7awp.png" alt="2.png" width="320" height="190"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 2:&lt;/strong&gt; Different levels of scope at which RBAC can be configured.&lt;/p&gt;

&lt;p&gt;This system allows you to define granular access to your resources by your corporate users.&lt;/p&gt;

&lt;h1&gt;
  
  
  Federation Tutorial
&lt;/h1&gt;

&lt;p&gt;Now that you know how RBAC works and the idea behind the federation between an Azure AD Custom Domain and an external IdP, let's focus on the Federation Tutorial steps.&lt;/p&gt;

&lt;h2&gt;
  
  
  1) G Suite SAML Application setup
&lt;/h2&gt;

&lt;p&gt;The first step of this tutorial is about creating a &lt;strong&gt;Custom SAML Application&lt;/strong&gt; inside the G Suite Admin Console. This application represents your Service Provider, i.e. Microsoft Azure, in the G Suite side.&lt;/p&gt;

&lt;p&gt;The Custom SAML Application contains all the information needed to send a digitally signed XML document containing the identity provider's authenticated identity to the Service Provider.&lt;/p&gt;

&lt;p&gt;This XML document is called &lt;strong&gt;SAML Assertion&lt;/strong&gt; and will be signed by the Identity Provider using an &lt;strong&gt;X.509 Certificate&lt;/strong&gt; shared with the Service Provider.&lt;/p&gt;

&lt;p&gt;The Service Provider uses the shared Certificate to retrieve and validate the SAML Assertion.&lt;/p&gt;

&lt;p&gt;Once logged into the Admin Console, navigate to &lt;strong&gt;Apps&lt;/strong&gt; from the Dashboard. From the Apps menu, select &lt;strong&gt;SAML apps&lt;/strong&gt;. The SAML apps section provides you a list of the existing SAML Applications and allows you to create a new one by clicking the plus yellow button on the page's bottom right.&lt;/p&gt;

&lt;p&gt;A new 5-steps wizard will be opened; &lt;/p&gt;

&lt;p&gt;in the wizard's first step, select &lt;strong&gt;SETUP MY OWN CUSTOM APP&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Go on and choose &lt;strong&gt;Option 2&lt;/strong&gt; to download the IdP information in the form of &lt;strong&gt;IdP metadata&lt;/strong&gt;. IdP metadata is an XML file that contains the X.509 Certificate, too; that's why I suggest you store it in a secure place. Moreover, it will be used in the last step of this tutorial to configure Azure AD Custom Domain's authentication method as federated.&lt;/p&gt;

&lt;p&gt;At this point, you need to configure the Custom SAML Application's name, description, and logo; the last two properties are optional.&lt;/p&gt;

&lt;p&gt;In the wizard's fourth step, provide the following SSO details to configure your Custom SAML Application:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;ACS URL&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt; The Service Provider's URL to which the SAML Assertion will be forwarded once the user has authenticated himself successfully. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Value:&lt;/strong&gt; &lt;code&gt;https://login.microsoftonline.com/login.srf&lt;/code&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Entity ID&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt; indicates the audience the SAML Assertion is intended. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Value:&lt;/strong&gt; &lt;em&gt;urn:federation:MicrosoftOnline&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Name ID&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt; SAML assertion attribute indicating who the user is. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Value:&lt;/strong&gt; &lt;em&gt;Basic Information &amp;gt; Primary email&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;&lt;strong&gt;Name ID Format&lt;/strong&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Description:&lt;/strong&gt; defines Name ID's format. &lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Value:&lt;/strong&gt; &lt;em&gt;PERSISTENT&lt;/em&gt;&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frjmys0ybawp3nt2vi3qw.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Frjmys0ybawp3nt2vi3qw.png" alt="3.png" width="628" height="407"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 3:&lt;/strong&gt; SAML Application's Service Provider Details definition.&lt;/p&gt;

&lt;p&gt;The last step consists of the attribute mapping definition, which is used to determine a mapping between attributes defined inside the SAML Assertion and attributes used inside the Service Provider. In this case, it is not necessary to define them, while it is fundamental if you want to federate a G Suite Organisational Unit with an AWS Account, but this is not the case.&lt;/p&gt;

&lt;p&gt;Once created, you should be able to see the SAML Application in the SAML apps section.&lt;/p&gt;

&lt;h2&gt;
  
  
  2) Azure AD Custom Domain Name setup
&lt;/h2&gt;

&lt;p&gt;In this step, we will configure a new Azure AD Custom Domain Name; you can skip it if you've already created one that suits your needs.&lt;/p&gt;

&lt;p&gt;Move to Azure Active Directory service in the Azure management console, and select &lt;strong&gt;Custom domain names&lt;/strong&gt; in the left sidebar to open the relative section.&lt;/p&gt;

&lt;p&gt;If you've never created a custom domain before, you should see only one domain, i.e. the default primary domain which name ends with &lt;strong&gt;&lt;code&gt;.onmicrosoft.com&lt;/code&gt;&lt;/strong&gt;. If this is your case, please leave it as your primary domain.&lt;/p&gt;

&lt;p&gt;Now click on &lt;strong&gt;+ Add custom domain&lt;/strong&gt; to create a new custom domain. A right sidebar will appear; here, you have to specify the new custom domain's name.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3s7k0m18i81dc2004mjt.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F3s7k0m18i81dc2004mjt.png" alt="4.png" width="800" height="536"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 4:&lt;/strong&gt; Add custom domain.&lt;/p&gt;

&lt;p&gt;Once the custom domain name is specified, you can move to the domain verification step by clicking the &lt;strong&gt;Add domain&lt;/strong&gt; button.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb2vo85jcg9mtk1ty784g.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fb2vo85jcg9mtk1ty784g.png" alt="5.png" width="800" height="529"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 5:&lt;/strong&gt; Custom domain verification.&lt;/p&gt;

&lt;p&gt;As illustrated in Figure 5, you need to verify the newly created custom domain name by creating a TXT record with your domain name registrar using the provided information. As your custom domain has been verified, its &lt;strong&gt;Status&lt;/strong&gt; attribute should appear as &lt;strong&gt;Verified&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;DON'T&lt;/strong&gt; set the new custom domain as the primary one; otherwise, you will not be able to federate it to the external Identity Provider.&lt;/p&gt;

&lt;h2&gt;
  
  
  3) Users import
&lt;/h2&gt;

&lt;p&gt;To enable corporate users to access your Azure Subscriptions, you have to add them to your Azure Active Directory before federating the custom domain to G Suite.&lt;/p&gt;

&lt;p&gt;You can do that from Azure Active Directory's &lt;strong&gt;Users&lt;/strong&gt; section, which is reachable by clicking Users in the left sidebar.&lt;/p&gt;

&lt;p&gt;You can add new users to your Azure Active Directory in the Users section by clicking &lt;strong&gt;+ New user&lt;/strong&gt;. You can even upload a CSV file containing your corporate users by clicking &lt;strong&gt;Bulk operations &amp;gt; Bulk create&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2py1hkd0z2ia7d7yuph.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fx2py1hkd0z2ia7d7yuph.png" alt="6.png" width="800" height="305"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 6:&lt;/strong&gt; Azure Active Directory users creation.&lt;/p&gt;

&lt;p&gt;Before proceeding with the federation setup, remember to set users' &lt;strong&gt;ImmutableId&lt;/strong&gt;. You may wonder what ImmutableId is? Well, it is an attribute that uniquely identifies a user in Azure Active Directory's context. To make federated Access work fine, ImmutableId should correspond to the user's email address.&lt;/p&gt;

&lt;p&gt;You can configure Users' ImmutableId using the &lt;strong&gt;Set-MsolUser&lt;/strong&gt; command from the PowerShell's &lt;strong&gt;MSOnline&lt;/strong&gt; module.&lt;/p&gt;

&lt;p&gt;To install the MSOnline module through PowerShell, use the following command:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Install-Module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;MSOnline&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Once installed, you can connect to your Azure Tenant through Connect-MsolService and set the user's ImmutableId through Set-MsolUser. Connect-MsolService requires you to authenticate with your Azure credentials.&lt;/p&gt;

&lt;p&gt;Be sure you are authenticating as a Member User and have sufficient privileges to run the Connect-MsolService command.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Connect-MsolService&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nx"&gt;Set-MsolUser&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-UserPrincipalName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;user-email&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nt"&gt;-ImmutableId&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;user-email&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If your necessity is to import many users to Azure AD, it would be easier to set their ImmutableId automatically. e.g., using a PowerShell script that iterates over the list of imported users and runs the Set-MsolUser command for each of them.&lt;/p&gt;

&lt;p&gt;At this point, imported Azure AD users, which belong to the newly created Custom Domain, can still not sign in using G Suite credentials since the Custom Domain has not yet been federated to the G Suite Organisational Unit.&lt;/p&gt;

&lt;p&gt;To make a practical example, you will be able to access Azure resources using the &lt;code&gt;az login&lt;/code&gt; command, but you can't do that providing your G Suite User credentials.&lt;/p&gt;

&lt;p&gt;So, let's move to the step that could appear innocent at first glance, but I guarantee a real pain when it's the first time you're dealing with it, causing you to struggle to find the right documentation setup to make it work fine.&lt;/p&gt;

&lt;h2&gt;
  
  
  4) Federation setup through PowerShell script
&lt;/h2&gt;

&lt;p&gt;Here we will see how to federate your Azure AD Custom Domain with your G Suite Organisational Unit using a PowerShell script cause it seems the only way to do that, at least in my experience.&lt;/p&gt;

&lt;p&gt;Here is the PowerShell script we used to set up the federation:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight powershell"&gt;&lt;code&gt;&lt;span class="n"&gt;Install-Module&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;MSOnline&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;Connect-MsolService&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="nv"&gt;$domainName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"&amp;lt;your-custom-domain-name&amp;gt;"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;xml&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nv"&gt;$idp&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Get-Content&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="err"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nx"&gt;metadata-xml-file-path&lt;/span&gt;&lt;span class="err"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$activeLogonUri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"https://login.microsoftonline.com/login.srf"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$signingCertificate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nv"&gt;$idp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EntityDescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IDPSSODescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;KeyDescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;KeyInfo&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;X509Data&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;X509Certificate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;Out-String&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;Trim&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$issuerUri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$idp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EntityDescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;entityID&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$logOffUri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$idp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EntityDescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IDPSSODescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SingleSignOnService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;span class="nv"&gt;$passiveLogOnUri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$idp&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;EntityDescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;IDPSSODescriptor&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;SingleSignOnService&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="w"&gt;

&lt;/span&gt;&lt;span class="n"&gt;Set-MsolDomainAuthentication&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-DomainName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$domainName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-FederationBrandName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$domainName&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-Authentication&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nx"&gt;Federated&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-PassiveLogOnUri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$passiveLogOnUri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-ActiveLogOnUri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$activeLogonUri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-SigningCertificate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$signingCertificate&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-IssuerUri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$issuerUri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-LogOffUri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="nv"&gt;$logOffUri&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="se"&gt;`
&lt;/span&gt;&lt;span class="w"&gt;  &lt;/span&gt;&lt;span class="nt"&gt;-PreferredAuthenticationProtocol&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="s2"&gt;"SAMLP"&lt;/span&gt;&lt;span class="w"&gt;
&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This script invokes three cmdlets:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Install-Module&lt;/strong&gt;, to install the MSOnline module, which contains the other cmdlets necessary to set up the federation between Azure AD and G Suite;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Connect-MsolService&lt;/strong&gt;, already described before, and used to connect to your Azure Tenant;&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Set-MsolDomainAuthentication&lt;/strong&gt;, to set up the Custom Domain's authentication method to federated.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;I suggest looking at the &lt;a href="https://docs.microsoft.com/en-us/powershell/module/msonline/set-msoldomainauthentication?view=azureadps-1.0" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; page for a complete description of the Set-MsolDomainAuthentication cmdlet and its parameters.&lt;/p&gt;

&lt;p&gt;Let's focus on three parameters, except the &lt;strong&gt;DomainName&lt;/strong&gt; one, which corresponds to the Azure AD's Custom Domain Name you should already have set up.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Authentication&lt;/strong&gt; - These parameters make Azure AD manage authentication autonomously or delegate authentication to an external IdP, in this case, G Suite. To complete Azure AD delegate authentication, we set Authentication to &lt;strong&gt;Federated&lt;/strong&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;SigningCertificate&lt;/strong&gt; - The value associated with this parameter corresponds to the &lt;strong&gt;X.509 certificate&lt;/strong&gt; included in the &lt;strong&gt;metadata XML file&lt;/strong&gt; downloaded during the G Suite SAML Application creation phase. It is necessary for the Service Provider, i.e. Azure AD, as the gateway to Azure Subscriptions, to retrieve the &lt;strong&gt;signed&lt;/strong&gt; authentication response. As you can see from the script, the metadata XML file is loaded from the local path in which you placed it.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;PreferredAuthenticationProtocol&lt;/strong&gt; - It is crucial to specify &lt;strong&gt;SAMLP&lt;/strong&gt; as the protocol used to authenticate users against the Identity Provider, as we set up a SAML Application on the G Suite.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Keep your fingers crossed and run the script... Hopefully, a check in the &lt;strong&gt;Federated&lt;/strong&gt; column should appear!&lt;/p&gt;

&lt;p&gt;Finally, you've successfully federated your Azure AD Custom Domain with your G Suite Organisational Unit.&lt;/p&gt;

&lt;h1&gt;
  
  
  Now, log in! 🚀
&lt;/h1&gt;

&lt;p&gt;At this point, we have all the instruments set up to log into your Azure Tenant with your G Suite credentials; it's needless to say that, to test the federated single sign-on, you should have a G Suite User's credentials in your hands. The same User should be present in the Azure Active Directory, as explained before.&lt;/p&gt;

&lt;p&gt;Now let's demonstrate the flow described in &lt;strong&gt;Figure 1&lt;/strong&gt;, gaining Azure access tokens through &lt;strong&gt;&lt;a href="https://github.com/Noovolari/leapp" rel="noopener noreferrer"&gt;Leapp&lt;/a&gt;&lt;/strong&gt;, our Open Source credentials management tool.&lt;/p&gt;

&lt;p&gt;I've already federated my test G Suite Organisational Unit with my test Azure Tenant, which contains a Subscription accessible by my User as &lt;strong&gt;Reader&lt;/strong&gt;. The reader is the role of my User, on the Azure side, for the Subscription I want to access. This role assignment follows RBAC rules.&lt;/p&gt;

&lt;p&gt;Inside &lt;strong&gt;&lt;a href="https://github.com/Noovolari/leapp" rel="noopener noreferrer"&gt;Leapp&lt;/a&gt;&lt;/strong&gt;, to add a new Azure Subscription, click the &lt;strong&gt;+&lt;/strong&gt; square button on the top-right side of the accounts list, which is empty as you run &lt;strong&gt;&lt;a href="https://github.com/Noovolari/leapp" rel="noopener noreferrer"&gt;Leapp&lt;/a&gt;&lt;/strong&gt; for the first time.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcuakz2qkbx3yvau1nw6s.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcuakz2qkbx3yvau1nw6s.png" alt="7a.png" width="800" height="1121"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 7a:&lt;/strong&gt; Add an Azure Subscription using &lt;strong&gt;&lt;a href="https://github.com/Noovolari/leapp" rel="noopener noreferrer"&gt;Leapp&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;Then, click on the Azure icon to open the Azure Subscription creation form.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjvj2a58s8c5oq69ov2xa.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fjvj2a58s8c5oq69ov2xa.png" alt="7b.png" width="800" height="1118"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 7b:&lt;/strong&gt; Add an Azure Subscription using &lt;strong&gt;&lt;a href="https://github.com/Noovolari/leapp" rel="noopener noreferrer"&gt;Leapp&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;You've to provide the alias and the ID of your Azure Subscription; moreover, you've to supply the ID of the Tenant that contains the Subscription.&lt;/p&gt;

&lt;p&gt;Once saved, you should see the new Azure Subscription in the accounts list.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcesiqinbkaw1d0n7r2qk.png" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fcesiqinbkaw1d0n7r2qk.png" alt="8.png" width="800" height="1117"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Figure 8:&lt;/strong&gt; Newly created Azure Subscription shows up in the accounts list.&lt;/p&gt;

&lt;p&gt;By clicking the card associated with the Subscription, &lt;strong&gt;&lt;a href="https://github.com/Noovolari/leapp" rel="noopener noreferrer"&gt;Leapp&lt;/a&gt;&lt;/strong&gt; will initiate the federated single sign-on flow, assuming that you've set up federation correctly.&lt;/p&gt;

&lt;p&gt;What do I mean with the federated single sign-on flow? I mean prompting for a G Suite User's credentials since Azure AD delegates the authentication to G Suite.&lt;/p&gt;

&lt;p&gt;Under the hood, &lt;strong&gt;&lt;a href="https://github.com/Noovolari/leapp" rel="noopener noreferrer"&gt;Leapp&lt;/a&gt;&lt;/strong&gt; invokes the &lt;code&gt;az login&lt;/code&gt; command, opens a new tab in your default browser, and redirects you to the G Suite login page. If we provided the right credentials, we'd be authenticated and issue Azure CLI's commands from the terminal. In this case, as we've associated a Reader role to the Azure AD User, we can issue the &lt;code&gt;az vm list&lt;/code&gt; command to retrieve the list of VMs in the Subscription. The Azure CLI relies on the temporary credentials generated by &lt;strong&gt;&lt;a href="https://github.com/Noovolari/leapp" rel="noopener noreferrer"&gt;Leapp&lt;/a&gt;&lt;/strong&gt; and stored in the &lt;strong&gt;~/.azure/accessTokens.json&lt;/strong&gt; file.&lt;/p&gt;

&lt;h1&gt;
  
  
  Final considerations
&lt;/h1&gt;

&lt;p&gt;In this article we learned how to set up a federation between G Suite and Azure and the reason that drives the adoption of this access pattern. &lt;/p&gt;

&lt;p&gt;We applied this access pattern to a real use case in which we gained access to an Azure Subscription quickly and easily using &lt;strong&gt;&lt;a href="https://github.com/Noovolari/leapp" rel="noopener noreferrer"&gt;Leapp&lt;/a&gt;&lt;/strong&gt;.&lt;/p&gt;

&lt;p&gt;We control User's privileges inside our Azure Tenant through the Role-Based Access Control concept, which we will deepen in one of the next publications.&lt;/p&gt;

&lt;p&gt;For what concerns security, RBAC plays a key role in this scenario. In addition to assign proper roles to specific Users inside our Tenant, it may be necessary to add MFA on the IdP side, i.e. G Suite, to protect our Cloud Environment following best-practices.&lt;/p&gt;

&lt;h1&gt;
  
  
  That's all, folks!
&lt;/h1&gt;

&lt;p&gt;I hope you enjoyed this blog post, and that it gave a clear understanding of how SAML federated access to Azure from G Suite can be set up and controlled, from a security point of view. &lt;/p&gt;

&lt;p&gt;Of course, this is only one of the possible configurations enabling access to Azure; have you ever find yourself to deal with this, or similar use cases? Are there any other related aspects you'd like to explore?&lt;/p&gt;

&lt;p&gt;Give us your feedback! It is always welcome and appreciated, and allows us to provide better content, aligned to real world applications.&lt;/p&gt;

</description>
      <category>azure</category>
      <category>gsuite</category>
      <category>sso</category>
      <category>opensource</category>
    </item>
  </channel>
</rss>
