
How Perfsys Accesses Customer AWS Accounts With Keycloak and saml2aws
Published on Nov 10, 2026
Table of Contents
- How Does Perfsys Get Access to a Client's AWS Account?
- What Does the Client Set Up in AWS IAM?
- What Do We Set Up in Keycloak?
- How Do Engineers Sign In to the AWS Console?
- Why Use saml2aws to Log In to the AWS CLI With SAML?
- How Do You Configure saml2aws for Each Client?
- How Do You Log In and Use the Profile?
- What Errors Did We Hit With AWS SAML Login?
- What Can the Client See and Revoke?
- FAQ
- How Does Perfsys Get Access to a Client's AWS Account?
- What Does the Client Set Up in AWS IAM?
- What Do We Set Up in Keycloak?
- How Do Engineers Sign In to the AWS Console?
- Why Use saml2aws to Log In to the AWS CLI With SAML?
- How Do You Configure saml2aws for Each Client?
- How Do You Log In and Use the Profile?
- What Errors Did We Hit With AWS SAML Login?
- What Can the Client See and Revoke?
- FAQ
Perfsys engineers get into a client's AWS account through SAML federation, with no password or access key involved. The client creates one IAM role that trusts Keycloak, the open-source identity server we run. Our engineers sign in to Keycloak with MFA, and AWS hands them credentials that expire after an hour. On the command line, saml2aws, a small tool that signs in to Keycloak for you, handles that exchange. Here is how both sides set it up, and what went wrong for us along the way.
How Does Perfsys Get Access to a Client's AWS Account?
Through SAML federation, an open standard that lets one system, here our Keycloak, vouch for a user to another, here AWS. The client registers our Keycloak as a SAML identity provider in their account and creates a role that only that provider can assume.
Perfsys is an AWS Select Tier Partner that helps startups and SMBs with cloud migration and managed AWS services, so working inside client accounts is part of the job. We decide which of our engineers can use that role. Nobody on our team has an IAM user in the client's account, and no long-lived keys exist to leak or rotate.
- An engineer signs in to Perfsys Keycloak with their own account and MFA.
- Keycloak issues a signed SAML assertion that names the client's role.
- The engineer's browser, or saml2aws on the command line, passes the assertion to AWS STS through
AssumeRoleWithSAML. STS validates the signature with the key in the metadata the client uploaded for the provider, so the caller needs no AWS credentials. - The engineer gets temporary credentials for that role. AWS sets the session to one hour by default, and a role can allow anywhere from 1 to 12 hours. We keep it at one hour.
For a comparison with IAM Identity Center and commercial identity providers, read Keycloak SSO on AWS: Is It Right for Your Team? This post covers the day-to-day mechanics. AWS describes the underlying model in its guide to SAML 2.0-based federation.
What Does the Client Set Up in AWS IAM?
Two IAM resources, both in the client's own account and under their control:
- A SAML identity provider, created in IAM from the metadata XML we send. We usually call it
SAML-Perfsys, so it is easy to find later. - An IAM role that trusts only that provider. The client chooses its permissions. For a discovery or audit engagement, we ask for the AWS managed
ReadOnlyAccesspolicy and nothing else.
The SAML:aud condition checks that the assertion was issued specifically for AWS sign-in. AWS describes this trust policy in its guide to creating a role for SAML 2.0 federation:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Federated": "arn:aws:iam::111122223333:saml-provider/SAML-Perfsys"
},
"Action": "sts:AssumeRoleWithSAML",
"Condition": {
"StringEquals": {
"SAML:aud": "https://signin.aws.amazon.com/saml"
}
}
}
]
}We also ask the client to keep the role's maximum session duration at one hour (3600 seconds). AWS allows anywhere from 1 to 12 hours, but nobody on our side needs longer sessions, and shorter ones limit the damage if a laptop is stolen.
What Do We Set Up in Keycloak?
For each client account we create one SAML client in our Keycloak realm. AWS reads the role from a SAML attribute named https://aws.amazon.com/SAML/Attributes/Role. Its value is two ARNs joined by a comma, the role and the provider:
arn:aws:iam::111122223333:role/perfsys-readonly,arn:aws:iam::111122223333:saml-provider/SAML-PerfsysWe store that string as a Keycloak client role and assign it only to the engineers on the engagement. When someone leaves the project, we remove the assignment in Keycloak. The client has nothing to clean up, because their account never knew about individual people.
💡 Pro tip: the role name in Keycloak is not checked against AWS. If you type a role that does not exist in the client account, Keycloak still offers it in the role picker, and AWS rejects it only at sign-in. Annoying. Before assigning a role, confirm that the client actually created it, with the exact name.
How Do Engineers Sign In to the AWS Console?
They open the Keycloak sign-in URL for that client. Keycloak posts the assertion to https://signin.aws.amazon.com/saml, and AWS opens the console as the assumed role. If an engineer has more than one role in the same account, AWS shows a role picker first. For console work, nothing more is needed. Simple as that.
Why Use saml2aws to Log In to the AWS CLI With SAML?
The AWS CLI cannot sign in through a SAML identity provider by itself. aws sts assume-role-with-saml exists, but it expects you to pass in a base64-encoded SAML assertion, which you would have to copy out of the browser by hand every hour.
saml2aws is an open-source command-line tool that converts your Keycloak SAML sign-in into temporary AWS STS keys. It handles the Keycloak login for you, MFA prompt included. Then it extracts the assertion and calls STS. The temporary credentials land in a named profile in ~/.aws/credentials. After that, every AWS tool that reads profiles works as usual, including the AWS CLI and Terraform.
How Do You Configure saml2aws for Each Client?
Install it and create one account entry per client. The -a name is local and only identifies the entry. Pick something you will recognise next to your other clients:
brew install saml2aws
saml2aws configure \
-a acme-readonly \
--idp-provider KeyCloak \
--mfa Auto \
--url https://sso.example.com/realms/example/protocol/saml/clients/amazon-aws-acme \
--username jdoe \
--role arn:aws:iam::111122223333:role/perfsys-readonly \
--profile acme-readonly \
--session-duration 3600 \
--skip-promptThis writes a section to ~/.saml2aws, a plain INI file that you can also edit by hand:
[acme-readonly]
name = acme-readonly
url = https://sso.example.com/realms/example/protocol/saml/clients/amazon-aws-acme
username = jdoe
provider = KeyCloak
mfa = Auto
aws_profile = acme-readonly
role_arn = arn:aws:iam::111122223333:role/perfsys-readonly
region = us-east-1
aws_session_duration = 3600The file holds no password or token. saml2aws asks for your password when you sign in, and on macOS it can save the password in the Keychain.
Even so, keep ~/.saml2aws out of dotfile repositories, because it reveals which client accounts you work with.
How Do You Log In and Use the Profile?
Run saml2aws login with the account name, then point your tools at the profile it wrote:
saml2aws login -a acme-readonly
export AWS_PROFILE=acme-readonly AWS_REGION=us-east-1
aws sts get-caller-identityaws sts get-caller-identity should return an ARN like arn:aws:sts::111122223333:assumed-role/perfsys-readonly/jdoe. The last part is the session name of your sign-in, and the client sees that same session in CloudTrail for every call you make.
Setting role_arn in the config file skips the role picker. Without it, saml2aws lists every role your Keycloak user holds for that client and asks you to choose one.
What Errors Did We Hit With AWS SAML Login?
Four problems cost us time, and each one is now on our onboarding checklist.
AccessDenied: Not authorized to perform sts:AssumeRoleWithSAML. Almost always the role ARN in Keycloak does not match a real role, or the role's trust policy names a different provider. Ask the client to runaws iam get-roleon the exact name. In our case, the client had created their own role instead of the one we suggested, and Keycloak was still offering ours.DurationSeconds exceeds the MaxSessionDuration. Theaws_session_durationin~/.saml2awsis longer than the role allows. AWS accepts anything from 900 seconds up to the role's maximum, so match it to that limit.Unknown optionsfrom the AWS CLI in zsh. Putting--profile x --region yin one shell variable and writingaws $OPTS ...does not work in zsh, because zsh does not split variables into separate words. ExportAWS_PROFILEandAWS_REGIONinstead. It is a classic zsh trap, and we fell into it.- Credentials that stop working after an hour. This is the design working as intended. Run
saml2aws loginagain. Scripts that run longer than an hour need to be split, or need a role with a longer session limit that the client agrees to.
What Can the Client See and Revoke?
Everything. Each API call appears in CloudTrail under the assumed role, and the sign-in itself is logged with the SAML NameID from our Keycloak. The client can end our access at any time without asking us, either by deleting the role or by deleting the SAML provider. Because there are no keys to find and deactivate, offboarding a partner takes minutes.
We think this is the right default for any consultancy that needs cross-account access to client AWS accounts. You own the door, and we only keep the list of people who can knock. Every visit is temporary and logged.
Want to see Keycloak working on the client side? Read our case studies on implementing Keycloak SSO on AWS for a large energy customer platform and how my-vpa unified access management and cut costs with AWS and Keycloak. For the service behind them, see our Keycloak SSO solution.
FAQ
No. You create one IAM role that trusts our SAML identity provider. Our engineers get temporary credentials for that role through Keycloak. Your account has no IAM users or long-lived access keys for us.
Yes. The permissions come from the policies you attach to the role. For discovery and audits we ask only for the AWS managed ReadOnlyAccess policy. If later work needs to make changes, you can add a separate role with wider permissions and remove it when the work is done.
Only for command-line access. The AWS console works directly from the Keycloak sign-in page. saml2aws exchanges the Keycloak sign-in for temporary credentials that tools like the AWS CLI and Terraform can use.
Delete the IAM role or the SAML identity provider in your account. No Perfsys engineer can start a new session after that, and any session that is already open expires within an hour.
One hour by default. AWS allows role sessions of 1 to 12 hours, and we ask clients to keep the maximum at one hour.

Tell us about your AWS setup, and we will show you how we get read-only access on day one without creating a single IAM user.
CEO & Founder @ Perfsys | Serverless architect with 10+ years of hands-on experience designing cloud-native architectures on AWS, backed by multiple AWS certifications. His writing bridges deep technical expertise with real-world business strategy, covering topics from AWS best practices to scaling tech-driven organizations.
AWS Experts, On-Demand
Need to move fast? Our cloud team is ready to scale, secure, and optimize your systems. Get serverless expertise, 24/7 support, and seamless CI/CD pipelines when you need it most.
Please accept cookies to load the booking widget.
