Add aws app and config for mfa.
Signed-off-by: jmug <u.g.a.mariano@gmail.com>
This commit is contained in:
parent
d72369c20b
commit
c4b62ddeee
5 changed files with 169 additions and 3 deletions
|
|
@ -4,8 +4,9 @@
|
|||
settings = {
|
||||
general = {
|
||||
lock_cmd = "pidof hyprlock || hyprlock"; # Avoid starting hyprlock multiple times.
|
||||
before_sleep_cmd = "loginctl lock-session"; # lock before suspend.
|
||||
before_sleep_cmd = "pidof hyprlock || hyprlock --no-fade-in --immediate"; # lock before suspend.
|
||||
after_sleep_cmd = "hyprctl dispatch dpms on"; # to avoid having to press a key twice to turn on the display.
|
||||
inhibit_sleep = 3; # Wait for hyprlock.
|
||||
};
|
||||
listener = [
|
||||
{
|
||||
|
|
|
|||
|
|
@ -20,6 +20,8 @@
|
|||
"private_keys/ace" = {
|
||||
path = "/home/jmug/.ssh/id_ace";
|
||||
};
|
||||
"aws/mfa_serial" = {};
|
||||
"aws/role_arn" = {};
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,6 +62,9 @@ in
|
|||
# Dev tools
|
||||
flyctl
|
||||
pkgs-unstable.claude-code
|
||||
# AWS tools
|
||||
awscli2
|
||||
(callPackage ../../nixos-modules/shell-apps/aws-cli-mfa.nix {})
|
||||
];
|
||||
|
||||
pointerCursor = {
|
||||
|
|
@ -155,8 +158,19 @@ in
|
|||
fly = "flyctl";
|
||||
# TODO: Interpolate the name of the host here.
|
||||
nrsw = "sudo nixos-rebuild switch --flake /home/jmug/nixos#asahi"; # parametrize this as home dir.
|
||||
awsmfa = "eval $(aws-cli-mfa)";
|
||||
uawsmfa = "eval $(aws-cli-mfa --unset)";
|
||||
};
|
||||
|
||||
# Let Home Manager install and manage itself.
|
||||
programs.home-manager.enable = true;
|
||||
|
||||
home.activation.aws-cli-mfa-config = lib.hm.dag.entryAfter ["writeBoundary"] ''
|
||||
mkdir -p ~/.config/aws-cli-mfa
|
||||
cat > ~/.config/aws-cli-mfa/config.yaml << EOF
|
||||
mfa_serial: $(cat ${config.sops.secrets."aws/mfa_serial".path})
|
||||
role_arn: $(cat ${config.sops.secrets."aws/role_arn".path})
|
||||
session_duration: 43200
|
||||
EOF
|
||||
'';
|
||||
}
|
||||
|
|
|
|||
146
nixos-modules/shell-apps/aws-cli-mfa.nix
Normal file
146
nixos-modules/shell-apps/aws-cli-mfa.nix
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
{ pkgs }:
|
||||
pkgs.writeShellApplication {
|
||||
name = "aws-cli-mfa";
|
||||
runtimeInputs = with pkgs; [
|
||||
awscli2
|
||||
yubikey-manager
|
||||
yq-go
|
||||
jq
|
||||
];
|
||||
text = ''
|
||||
set -euo pipefail
|
||||
|
||||
CONFIG_DIR="$HOME/.config/aws-cli-mfa"
|
||||
CONFIG_FILE="$CONFIG_DIR/config.yaml"
|
||||
|
||||
usage() {
|
||||
echo "Usage: $0 [--unset] [--help]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " --unset Unset AWS environment variables"
|
||||
echo " --help Show this help message"
|
||||
echo ""
|
||||
echo "This tool assumes temporary credentials with MFA using a YubiKey."
|
||||
echo "Configuration file: $CONFIG_FILE"
|
||||
}
|
||||
|
||||
unset_vars() {
|
||||
if [[ -t 1 ]]; then
|
||||
# Running directly - can't unset in parent shell, show instructions
|
||||
echo "To unset AWS environment variables, run:"
|
||||
echo " eval \$(aws-cli-mfa --unset)"
|
||||
else
|
||||
# Running from eval - output unset commands
|
||||
echo "AWS environment variables unset." >&2
|
||||
cat << EOF
|
||||
unset AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN AWS_SECURITY_TOKEN
|
||||
EOF
|
||||
fi
|
||||
}
|
||||
|
||||
# Parse command line arguments
|
||||
if [[ $# -gt 0 ]]; then
|
||||
case "$1" in
|
||||
--unset)
|
||||
unset_vars
|
||||
exit 0
|
||||
;;
|
||||
--help)
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
echo "Unknown option: $1"
|
||||
usage
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
fi
|
||||
|
||||
# Check if config file exists
|
||||
if [[ ! -f "$CONFIG_FILE" ]]; then
|
||||
echo "Error: Configuration file not found: $CONFIG_FILE"
|
||||
echo ""
|
||||
echo "Please create a configuration file with the following format:"
|
||||
echo ""
|
||||
echo "mfa_serial: arn:aws:iam::123456789012:mfa/username"
|
||||
echo "role_arn: arn:aws:iam::123456789012:role/RoleName"
|
||||
echo "session_duration: 43200 # optional, defaults to 43200 seconds (12 hours)"
|
||||
echo ""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Read configuration
|
||||
MFA_SERIAL=$(yq eval '.mfa_serial' "$CONFIG_FILE")
|
||||
ROLE_ARN=$(yq eval '.role_arn' "$CONFIG_FILE")
|
||||
SESSION_DURATION=$(yq eval '.session_duration // 43200' "$CONFIG_FILE")
|
||||
|
||||
if [[ "$MFA_SERIAL" == "null" || "$ROLE_ARN" == "null" ]]; then
|
||||
echo "Error: mfa_serial and role_arn must be specified in $CONFIG_FILE"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Getting TOTP code from YubiKey for device: $MFA_SERIAL" >&2
|
||||
|
||||
# Get TOTP code from YubiKey
|
||||
if ! TOTP_CODE=$(ykman oath accounts code "$MFA_SERIAL" -s); then
|
||||
echo "Error: Failed to get TOTP code from YubiKey for device '$MFA_SERIAL'"
|
||||
echo "Available OATH accounts:"
|
||||
ykman oath accounts list || echo "No OATH accounts found on YubiKey"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Assuming role with MFA..." >&2
|
||||
|
||||
# Call AWS STS assume-role
|
||||
if ! STS_RESPONSE=$(aws sts assume-role \
|
||||
--role-arn "$ROLE_ARN" \
|
||||
--role-session-name "aws-cli-mfa-$(date +%s)" \
|
||||
--serial-number "$MFA_SERIAL" \
|
||||
--token-code "$TOTP_CODE" \
|
||||
--duration-seconds "$SESSION_DURATION" \
|
||||
--output json); then
|
||||
echo "Error: Failed to assume role. Check your AWS credentials and configuration."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract credentials from response
|
||||
AWS_ACCESS_KEY_ID=$(echo "$STS_RESPONSE" | jq -r '.Credentials.AccessKeyId')
|
||||
AWS_SECRET_ACCESS_KEY=$(echo "$STS_RESPONSE" | jq -r '.Credentials.SecretAccessKey')
|
||||
AWS_SESSION_TOKEN=$(echo "$STS_RESPONSE" | jq -r '.Credentials.SessionToken')
|
||||
EXPIRATION=$(echo "$STS_RESPONSE" | jq -r '.Credentials.Expiration')
|
||||
|
||||
if [[ "$AWS_ACCESS_KEY_ID" == "null" || "$AWS_SECRET_ACCESS_KEY" == "null" || "$AWS_SESSION_TOKEN" == "null" ]]; then
|
||||
echo "Error: Failed to extract credentials from AWS response"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Check if running from eval (stdout is a pipe) or directly
|
||||
if [[ -t 1 ]]; then
|
||||
# Running directly - can't export to parent shell, show instructions
|
||||
echo "Success! AWS temporary credentials retrieved."
|
||||
echo "Credentials expire at: $EXPIRATION"
|
||||
echo ""
|
||||
echo "To use these credentials in your current shell, run:"
|
||||
echo " eval \$(aws-cli-mfa)"
|
||||
echo ""
|
||||
echo "To unset the credentials later, run:"
|
||||
echo " eval \$(aws-cli-mfa --unset)"
|
||||
else
|
||||
# Running from eval - only output export commands
|
||||
echo "Success! AWS temporary credentials have been set." >&2
|
||||
echo "Credentials expire at: $EXPIRATION" >&2
|
||||
echo "" >&2
|
||||
echo "To unset the credentials later, run:" >&2
|
||||
echo " eval \$(aws-cli-mfa --unset)" >&2
|
||||
|
||||
# Output export commands for eval
|
||||
cat << EOF
|
||||
export AWS_ACCESS_KEY_ID='$AWS_ACCESS_KEY_ID'
|
||||
export AWS_SECRET_ACCESS_KEY='$AWS_SECRET_ACCESS_KEY'
|
||||
export AWS_SESSION_TOKEN='$AWS_SESSION_TOKEN'
|
||||
export AWS_SECURITY_TOKEN='$AWS_SESSION_TOKEN'
|
||||
EOF
|
||||
fi
|
||||
'';
|
||||
}
|
||||
|
|
@ -2,6 +2,9 @@ private_keys:
|
|||
jmug: ENC[AES256_GCM,data:OOokznYtow9Ra0FRwBydclS6Z7w7mV9RTtHpjyw8NT+rV2VzTm/K8qYSw9N3gDbao5JOZH+LlVIL0UX2ZqGk8j/4D67LP+FmTUiIqyHH3LI8RcXAixIbR+zwV19Gr7DiFWw8jCyXQFFBJJRIatZLA5T2r23pYxL5drpQUcWsttuHRN7RwfXq2eFQogufzgfUqQgMkqvx64prDbrNq7bqZpPZE/vrCIoSK4rgTZCokD2hoIdEdzxLaVlbaoMMY7Dg83ojFU2Fpe5TWuS+duxUYjCPh86uoa3d0dsKoVkB9zd56EO5z0SB94tht9WJzmqKPh2gZ6DvV+wdaMH7wSqnUB6c2mE3i886Y4LQJjUFzpu1dnZaEEvJ0HI5jelZ3QVwjhp8/Zrkl/MwOG+lCHcIu2T7nQ/O0NxBNgMYbEYHGDcqi+anAzw2eNfep//dC+lT0qiXYAlzdDIIcTE7sL40qq7xXWtZJR4I6B+EOcYVn+zu93tsLiNke26h9ZoiAk40oxNZaiTPKnLkSvPtVZcoA53PamVKTS+tkXd+Pzt07lUgumTRIybkjE7i0hrhBrAv98NqvHobWfJVsQaH,iv:CDOXxoNTTw0rTsQbyYcXk0xL1UZtSbC0EG0audUwriM=,tag:XN2sujg9YHc5FtwCGPweSQ==,type:str]
|
||||
matcha: ENC[AES256_GCM,data:ySty7UiMQirmXmTf0unJuWX731NKKHH0lJQUxl4LlOHixm+1I13SNF7g+G9XYQzkvX/ijhzkDGLwIERVq1Di1UJsEw5w2YxeSitrzoJT0NZx+/Ip8DdgD/k+KnWgm7NeswcUTlt5cQbw7/IPkmRZ3qOV9UueMhH09AYEaSLpiKBUKQuMP/u2YgklwgWvVxW6syMPiYWmSnEfP3MfnkUbhhCuexdb2a/26BfVBbZeuLgBi25dxvRlykR6/uijCk3lHl84xPgWGKyR/130aHC2wp3arVjWO8/p2h2dobtnEnnDCWz2t+3CD1Qc3kdJcSNXhlFJWESOxzJp2KZFIKc3tF4emRSJ+EwP9byavrRozkHCBx4qCvLfdBzndJalR6ebh3jMyQIdRNBPG4x7+nSNnWZeK2uXhHg+m18CJfq2nKgVrpB4x+i48LyEwv907hFGLhfB4o+gfHxQtJYNoP3F0HX2xYndIjk6ihzbUi4C4YG7eUOF1IQ174FshFiadLfqAS+yh8oDUpKVthRu8kda6pPCtMI2jugIYzFrA30k6RWSj6QIsV8FE/jUdw++Htw9dutJSVsAncqCy4mZvqTIh0Cubnp9seBHX0l7vX0kAznoUMTK07lHBbkyeVlZHvKA+y34+SJVLpuS1eVjNhkeNpKkWAxwkoc/84ozpM2078bzy48rvMJBYIzjgqnqREnSs35Q8bQcHB32R0T6JEPoT7S8Z1GS7QB7kv8ulbA2H11Z,iv:8EBPvh7dpv23NtgwUmLn+2m/CKI6dZq72AXvB1OOdlc=,tag:1RCXZDcLOUP+hznVRgzMuA==,type:str]
|
||||
ace: ENC[AES256_GCM,data:rqhEzNlR978ZS+OppyHOWjYTfRKifRMXpqQfKS48oHkbcq7fQF6QtBBz3Ad4yFE3UJECcPipWqi5dhAMDVmOZT9gxEvEdhf6T7ecPHuQo95eUGPC46ZjoEwv7bykNBcncZFd4EHU2szuyqWb+xpGwJtnKqxDzi0ygsS6z/8ySlJWJ+LqCWrwsnERIblW5vgCvrT5Q2zkz3mR8pDNFc4Kh7B27SCBFG3EHST/NsEMhW0hU2eoIK5ppvHaKhVTx22ov2dP+nNbAhMi1WqHCGyQC2X4jeGGPXV8qXvev3Dl0s/VTCUsyqIIU5hPggWo++/XEspaoiLX7BsGklcfL5qGbF6YmSHYDBdgs5VOTzRUsepegmF79qXKO2XRgksH0he3aUOkpv9TVsmBIyPWqClOtA/QiQQ12gLCvqmBLcj66prvRS9qsZ++wxIINBFWhZh8F24pUHf6qpLpXmiEz9l7n1WocJjVgsI0hebYNN7sLtX/2IxVhPjNHVJQPPkDdLuw2841QKdO8cyDjCho3gbm1+RRDeyZWFSnnQUnKA+p2rE9ahtIJtUTuri7egGroJxPRWwgx2r3FW1Cm1ScdcL2W2AJQtnlJNqRnK/jXHXU3QHBkSiLTSwDLXG/0FV23/4Q+wCYp7ivBbztywT2Ngs8IMrFXz/6a7oGPaRqeendaVLJwrpkjruWv/nTdw0/PRchkLFuuP9ncJYVYaI2X6WwE9eiCAyG99M1X587w7SQe7cx,iv:HHfrC8PMHQS96YAzsyu7u52josTWNpgGa+qdjTKk7mk=,tag:9njC2670XZBUusf3cIv+gg==,type:str]
|
||||
aws:
|
||||
role_arn: ENC[AES256_GCM,data:YlYtqpsiTgHayuCFxY3pKfh5aBjNPf0UMGCoR+mFBUxe1CIU/Nkm+gzAOzwI,iv:Oo8d5y2g3lIVhrQgBT80PSxnZC0qXdqrumx76V1dz6w=,tag:gGJLjCYgcR3nHGhEbEpIGw==,type:str]
|
||||
mfa_serial: ENC[AES256_GCM,data:O1Tzop8mjG48Hw19tAVoTvQ/z4UR3MvXzyEZZ8RArp73E7GsrR6jtsXnbrtNrigTgA==,iv:HumTqCU69e7zAUMsTn4lKr1WY8hU/SS/p5N2IXPTVWY=,tag:ATfjwZGSDmCaV7Zuoe9XzA==,type:str]
|
||||
yubico:
|
||||
u2f_keys:
|
||||
jmug: ENC[AES256_GCM,data:Z42zNo1DaQutPIfE+0PEAK5F1fmspJp6jmosHSHsUN6dSG4zY93Tdmvisxg0hFUbuMlYg/06z3bsagFY4q+9Eg6qCLqzj1Uzs3VA0vEP+N0UlR5YZvneWzhnw2KYaPSJ/dsxt9tSfJO89P5ffeJgfSds2hLRWngm0agkmZ1P9lRbY0iMTUGl9se4V/anydwH69GQLyul5EtXHr9KZyU2pkT86zQSHGqiiMm85TfyixTWi/PWFl1jtDlyUbvN2HZYFGdQ6O0E,iv:TYel/hCVAMQL1rqok/1YMqcGFuXmsvkwUcA988VULW8=,tag:dnPQiY5i3oHbsC9zdXvY4w==,type:str]
|
||||
|
|
@ -44,7 +47,7 @@ sops:
|
|||
UjlDQ0Y5QnY4dmlVVFZrM0IyZzlISWcKwpQY9/f1O2v78/9/dCZ7HPE3wVwQ4COG
|
||||
a0E+oMEgBIeQny9LyfhUW2V/HKhYhFNPJaZrNM4J1zL+bz2ucdErmw==
|
||||
-----END AGE ENCRYPTED FILE-----
|
||||
lastmodified: "2025-06-19T19:52:49Z"
|
||||
mac: ENC[AES256_GCM,data:Fz/3QEoAjJy4psanCwDvIjUFSVDaSK+/Qjyr2M2c7eetv+USDaP1CraXaTK/OwKQfDWdnPHUOqfW1Oj51XJSPPoRlyYjXJxODjVXZfHo/EwnbpJs/81Lx66lYKljgCopFE6y2a7cFkM25g9aehyPhP/zdwULa/EmXcnuIimH8A0=,iv:dniso33D2uf4YUUbbODsbfm2k6dZdWdBTBPvnXTHL34=,tag:89KOctxIJ+lT7xUQR0qetA==,type:str]
|
||||
lastmodified: "2025-07-15T00:54:12Z"
|
||||
mac: ENC[AES256_GCM,data:KYcoP9vtmLRDaYVUfGtRy5XfHVgwuF6DxV2U2ZCQZ0oUTJRXj9eSjWJFRXlT243GQ11SgoUAcGFhATAOyqla3jsXuDiTn5oMydEwgSjVxjFpQf2RujCCqekk/7rcrRC7hVlUryNFylYy9wA9TWkGNGpaB/Z/a+Oaa5naDXODRAE=,iv:a6YVHIp4dIGxCIDmwM8r2AlBO40gptiLeNoyhRdJ+m8=,tag:DKsGjalA69F1ups/2sO5og==,type:str]
|
||||
unencrypted_suffix: _unencrypted
|
||||
version: 3.10.2
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue