📝

CircleCI Orb で 再利用可能なDeploy環境を整備する(AWS CLI + Node.js)

に公開

前回はCLIを入れたので今日はOrb(オーブ)を触っていきたいと思います。カガリ・ユラ・アスハではありません。
CircleCIの**Orb(オーブ)**とは、CI/CDの設定でよく使われる処理や構成をパッケージ化し、再利用できるようにしたもので、YAML形式で定義されており、ジョブ(job)、コマンド(command)、実行環境(executor)などをまとめて使うことができます。

複雑な設定をシンプルに記述でき、同じ処理を複数のプロジェクト間で共有することが可能となる、等のメリットがあります。たとえば、Node.jsのビルド、AWSへのデプロイ、Slack通知など、定型作業を1行で呼び出せるようになったり、AWS Credential設定の書式をよりシンプルにしたりすることが可能です。

Orb Registry

orb registryというサイトで公式やコミュニティが作成したOrbがそろっています。

例えばcircleci/aws-cli@5.4.0を使う場合
config.ymlに以下を記載することで利用可能となります。

version: '2.1'
orbs:
  aws-cli: circleci/aws-cli@5.1

さっそくやってみる

https://zenn.dev/kameoncloud/articles/c989cc650338e4
のブログ記事で構築した環境を利用します。この環境ではOrbを利用せずにAWSのクレデンシャルをContextというCircleCIの環境変数に保存したものを呼び出しています。

config.yml
# Use the latest 2.1 version of CircleCI pipeline process engine.
# See: https://circleci.com/docs/configuration-reference
version: 2.1

# Define a job to be invoked later in a workflow.
# See: https://circleci.com/docs/jobs-steps/#jobs-overview & https://circleci.com/docs/configuration-reference/#jobs
jobs:
  deploy-lambda:
    # Use an AWS-compatible Docker image
    docker:
      - image: cimg/python:3.9-node

    # Add steps to the job
    steps:
      # Checkout the code as the first step.
      - checkout
      
      # Set up Node.js environment
      - run:
          name: "Set up Node.js environment"
          command: |
            npm install
      
      # Run linting and tests
      - run:
          name: "Run linting and tests"
          command: |
            npm run lint || echo "Linting issues found, but continuing deployment"
            npm test
      
      # Install AWS CLI
      - run:
          name: "Install AWS CLI"
          command: |
            curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
            unzip awscliv2.zip
            sudo ./aws/install
      
      # Configure AWS credentials
      - run:
          name: "Configure AWS credentials"
          command: |
            # Set AWS credentials as environment variables (preferred method)
            export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
            export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
            export AWS_DEFAULT_REGION=ap-northeast-1
            
            # Verify credentials are working
            echo "Verifying AWS credentials..."
            aws sts get-caller-identity || {
              echo "AWS credentials verification failed. Please check your AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY."
              exit 1
            }
      
      # Create deployment package
      - run:
          name: "Create deployment package"
          command: |
            mkdir -p deploy
            cp index.mjs deploy/
            cd deploy
            zip -r lambda_function.zip .
      
      # Deploy Lambda function with URL
      - run:
          name: "Deploy Lambda function with URL"
          command: |
            # Ensure AWS credentials are set for this step
            export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
            export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
            export AWS_DEFAULT_REGION=ap-northeast-1
            
            # Verify AWS configuration
            echo "Using AWS Region: ap-northeast-1"
            aws configure list
            
            # Create or update Lambda function using AWS SAM
            echo "Deploying Lambda function with URL..."
            
            # First, try to create the function (will fail if it already exists)
            echo "Attempting to create new Lambda function..."
            aws lambda create-function \
              --region ap-northeast-1 \
              --function-name LambdaURL \
              --runtime nodejs18.x \
              --handler index.handler \
              --zip-file fileb://deploy/lambda_function.zip \
              --role $AWS_LAMBDA_ROLE_ARN || {
                
                # If creation fails, try to update the function
                echo "Function may already exist, attempting to update..."
                aws lambda update-function-code \
                  --region ap-northeast-1 \
                  --function-name LambdaURL \
                  --zip-file fileb://deploy/lambda_function.zip
            }
            
            # Create function URL (will fail silently if it already exists)
            echo "Configuring function URL..."
            aws lambda create-function-url-config \
              --region ap-northeast-1 \
              --function-name LambdaURL \
              --auth-type NONE || true
            
            # Get and display the Lambda URL
            echo "Retrieving function URL..."
            aws lambda get-function-url-config \
              --region ap-northeast-1 \
              --function-name LambdaURL || echo "Could not retrieve function URL. Please check the function in the AWS console."

# Orchestrate jobs using workflows
# See: https://circleci.com/docs/workflows/ & https://circleci.com/docs/configuration-reference/#workflows
workflows:
  deploy-lambda-workflow:
    # Inside the workflow, you define the jobs you want to run.
    jobs:
      - deploy-lambda:
          # Use the aws-credentials context to access AWS credentials
          context:
            - aws-credentials
          # Only run on main branch
          filters:
            branches:
              only: main

以下の部分でまずはAWS CLIをインストールしています。

      - run:
          name: "Install AWS CLI"
          command: |
            curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
            unzip awscliv2.zip
            sudo ./aws/install

次に以下のパートでCredentialをセットしています。

      - run:
          name: "Deploy Lambda function with URL"
          command: |
            # Ensure AWS credentials are set for this step
            export AWS_ACCESS_KEY_ID=$AWS_ACCESS_KEY_ID
            export AWS_SECRET_ACCESS_KEY=$AWS_SECRET_ACCESS_KEY
            export AWS_DEFAULT_REGION=ap-northeast-1

次にこのconfig.ymlをAWS CLI用Orbに変更したものが以下です。

config.yml
version: 2.1

orbs:
  aws-cli: circleci/aws-cli@4.0.0

jobs:
  deploy-lambda:
    executor: aws-cli/default
    steps:
      - checkout

      # AWS 認証情報のセットアップ(context 経由)
      - aws-cli/setup

      # Node.js を非 root 環境にバイナリでインストール
      - run:
          name: "Install Node.js 18 (binary)"
          command: |
            curl -fsSL https://nodejs.org/dist/v18.20.2/node-v18.20.2-linux-x64.tar.xz -o node.tar.xz
            mkdir -p /tmp/node
            tar -xf node.tar.xz -C /tmp/node --strip-components=1
            echo 'export PATH="/tmp/node/bin:$PATH"' >> $BASH_ENV
            source $BASH_ENV
            node -v
            npm -v

      # npm install
      - run:
          name: "Install dependencies"
          command: |
            source $BASH_ENV
            npm install

      # Lint & Test
      - run:
          name: "Run linting and tests"
          command: |
            source $BASH_ENV
            npm run lint || echo "Linting issues found, but continuing deployment"
            npm test

      # Lambda zip パッケージ作成
      - run:
          name: "Create deployment package"
          command: |
            mkdir -p deploy
            cp index.mjs deploy/
            cd deploy
            zip -r lambda_function.zip .

      # Lambda 関数の作成または更新 & URL取得
      - run:
          name: "Deploy Lambda function with URL"
          command: |
            echo "Deploying Lambda function..."

            aws lambda create-function \
              --region ap-northeast-1 \
              --function-name LambdaURL \
              --runtime nodejs18.x \
              --handler index.handler \
              --zip-file fileb://deploy/lambda_function.zip \
              --role $AWS_LAMBDA_ROLE_ARN || {
                echo "Function may already exist, attempting to update..."
                aws lambda update-function-code \
                  --region ap-northeast-1 \
                  --function-name LambdaURL \
                  --zip-file fileb://deploy/lambda_function.zip
              }

            echo "Creating function URL config..."
            aws lambda create-function-url-config \
              --region ap-northeast-1 \
              --function-name LambdaURL \
              --auth-type NONE || true

            echo "Retrieving Lambda URL..."
            aws lambda get-function-url-config \
              --region ap-northeast-1 \
              --function-name LambdaURL || echo "Could not retrieve function URL."

workflows:
  deploy-lambda-workflow:
    jobs:
      - deploy-lambda:
          context:
            - aws-credentials
          filters:
            branches:
              only: main

まずは以下のパートでorbを定義して呼び出しています。

orbs:
  aws-cli: circleci/aws-cli@4.0.0

そうするとあらかじめAWS CLIがインストール済の環境が起動するため上記にあったAWS CLI記載部分が不要となります。AWS Credentialの設定も非常にシンプルで以下の1行で済んでいます。

      - aws-cli/setup

AWS CLI専用環境を起動しており環境変数(Context)であるAWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY,AWS_DEFAULT_REGIONを自動で読み込んでいるためです。

Orb の中身とは / orb source コマンド

https://zenn.dev/kameoncloud/articles/707a448101e5c0
こちらの記事でインストールしたCircleCI CLIを使うことでOrbの中身(環境を定義しているyml)を見ることができます。
circleci orb source circleci/aws-cli@4.0.0

AWS CLI Orb の中身(クリックで展開)
version: 2.1
description: |
    Install and configure the AWS command-line interface (awscli) version 2.
    (To use AWS CLI v1 view version 1.4.1 of this orb)

    Supports Linux x86_64, MacOS, and Arm64 V8.
display:
    home_url: https://aws.amazon.com/cli
    source_url: https://github.com/CircleCI-Public/aws-cli-orb
commands:
    assume_role_with_web_identity:
        description: |
            Generate a shortlived AWS_ACCESS_KEY_ID, AWS_ACCESS_KEY_ID and AWS_SESSION_TOKEN using the $CIRCLE_OIDC_TOKEN_V2.   
            A properly configured web identity based ARN is also required for configuration.
            Use these keys and create a profile with the aws-cli/setup commands.
            For more information, see the CircleCI OIDC docs: https://circleci.com/docs/2.0/openid-connect-tokens/
        parameters:
            profile_name:
                default: default
                description: Profile name for web identity role assumption
                type: string
            role_arn:
                description: |
                    The Amazon Resource Name (ARN) of the role that the caller is assuming.
                    Role ARN must be configured for web identity.
                type: string
            role_session_name:
                default: ${CIRCLE_JOB}
                description: An identifier for the assumed role session
                type: string
            session_duration:
                default: "3600"
                description: The duration of the session in seconds
                type: string
        steps:
            - run:
                command: "# shellcheck disable=SC2148\nORB_EVAL_ROLE_SESSION_NAME=$(circleci env subst \"${ORB_EVAL_ROLE_SESSION_NAME}\")\nORB_EVAL_ROLE_ARN=$(circleci env subst \"${ORB_EVAL_ROLE_ARN}\")\nORB_EVAL_PROFILE_NAME=$(circleci env subst \"$ORB_EVAL_PROFILE_NAME\")\n\nif [ -z \"${ORB_EVAL_ROLE_SESSION_NAME}\" ]; then\n    echo \"Role session name is required\"\n    exit 1\nfi\n\nif [ -z \"${CIRCLE_OIDC_TOKEN_V2}\" ]; then\n    echo \"OIDC Token cannot be found. A CircleCI context must be specified.\"\n    exit 1\nfi\n\nif [ ! \"$(command -v aws)\" ]; then\n    echo \"AWS CLI is not installed. Please run the setup or install command first.\"\n    exit 1\nfi\n\nread -r AWS_ACCESS_KEY_ID AWS_SECRET_ACCESS_KEY AWS_SESSION_TOKEN \\<<EOF\n$(aws sts assume-role-with-web-identity \\\n--role-arn \"${ORB_EVAL_ROLE_ARN}\" \\\n--role-session-name \"${ORB_EVAL_ROLE_SESSION_NAME}\" \\\n--web-identity-token \"${CIRCLE_OIDC_TOKEN_V2}\" \\\n--duration-seconds \"${ORB_VAL_SESSION_DURATION}\" \\\n--query 'Credentials.[AccessKeyId,SecretAccessKey,SessionToken]' \\\n--output text)\nEOF\n\nif [ -z \"${AWS_ACCESS_KEY_ID}\" ] || [ -z \"${AWS_SECRET_ACCESS_KEY}\" ] || [ -z \"${AWS_SESSION_TOKEN}\" ]; then\n    echo \"Failed to assume role\";\n    exit 1\nelse \n    {\n        echo \"export AWS_ACCESS_KEY_ID=\\\"${AWS_ACCESS_KEY_ID}\\\"\"\n        echo \"export AWS_SECRET_ACCESS_KEY=\\\"${AWS_SECRET_ACCESS_KEY}\\\"\"\n        echo \"export AWS_SESSION_TOKEN=\\\"${AWS_SESSION_TOKEN}\\\"\"\n    } >>\"$BASH_ENV\"\n    echo \"Assume role with web identity succeeded\"\nfi\n"
                environment:
                    ORB_EVAL_PROFILE_NAME: <<parameters.profile_name>>
                    ORB_EVAL_ROLE_ARN: <<parameters.role_arn>>
                    ORB_EVAL_ROLE_SESSION_NAME: <<parameters.role_session_name>>
                    ORB_VAL_SESSION_DURATION: <<parameters.session_duration>>
                name: Generate shortlived AWS Keys using CircleCI OIDC token.
    install:
        description: Install the AWS CLI via Pip if not already installed.
        parameters:
            binary_dir:
                default: /usr/local/bin
                description: |
                    The main aws program in the install directory is symbolically linked to the file aws in the specified path. Defaults to /usr/local/bin
                type: string
            disable_aws_pager:
                default: true
                description: |
                    Set to false to skip forceful disabling of all AWS CLI output paging.
                type: boolean
            install_dir:
                default: /usr/local/aws-cli
                description: |
                    Specify the installation directory of AWS CLI. Defaults to /usr/local/aws-cli
                type: string
            override_installed:
                default: false
                description: |
                    By default, if the AWS CLI is detected on the system, the install will be skipped.
                    Enable this to override the installed version and install your specified version.
                type: boolean
            version:
                default: latest
                description: Select a specific version of the AWS v2 CLI. By default the latest version will be used.
                type: string
        steps:
            - run:
                command: |
                    # shellcheck disable=SC2148
                    if grep "Alpine" /etc/issue >/dev/null 2>&1; then
                        if [ "$ID" = 0 ]; then export SUDO=""; else export SUDO="sudo"; fi
                    else
                        if [[ $EUID == 0 ]]; then export SUDO=""; else export SUDO="sudo"; fi
                    fi

                    Install_AWS_CLI() {
                        echo "Installing AWS CLI v2"
                        cd /tmp || exit
                        # Platform check
                        if uname -a | grep "Darwin"; then
                            export SYS_ENV_PLATFORM=macos
                        elif uname -a | grep "x86_64 GNU/Linux"; then
                            export SYS_ENV_PLATFORM=linux_x86
                        elif uname -a | grep "aarch64 GNU/Linux"; then
                            export SYS_ENV_PLATFORM=linux_arm
                        elif uname -a | grep "x86_64 Msys"; then
                            export SYS_ENV_PLATFORM=windows
                        elif grep "Alpine" /etc/issue >/dev/null 2>&1; then
                            export SYS_ENV_PLATFORM=linux_alpine
                        else
                            echo "This platform appears to be unsupported."
                            uname -a
                            exit 1
                        fi

                        # Install per platform
                        case $SYS_ENV_PLATFORM in
                        linux_x86)
                            curl -sSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64$1.zip" -o "awscliv2.zip"
                            unzip -q -o awscliv2.zip
                            $SUDO ./aws/install -i "${ORB_VAL_INSTALL_DIR}" -b "${ORB_VAL_BINARY_DIR}"
                            rm -r awscliv2.zip ./aws
                            ;;
                        windows)
                            if [ ! "$(command -v choco)" ]; then
                                echo "Chocolatey is required to uninstall AWS"
                                exit 1
                            fi
                            choco install awscli --version="$1"
                            echo "$1"
                            if echo "$1" | grep "2."; then
                                echo "export PATH=\"\${PATH}:/c/Program Files/Amazon/AWSCLIV2\"" >> "$BASH_ENV"

                            else
                                echo "export PATH=\"\${PATH}:/c/Program Files/Amazon/AWSCLI/bin\"" >>"$BASH_ENV"
                            fi
                            ;;
                        macos)
                            curl -sSL "https://awscli.amazonaws.com/AWSCLIV2$1.pkg" -o "AWSCLIV2.pkg"
                            $SUDO installer -pkg AWSCLIV2.pkg -target /
                            rm AWSCLIV2.pkg
                            ;;
                        linux_arm)
                            curl -sSL "https://awscli.amazonaws.com/awscli-exe-linux-aarch64$1.zip" -o "awscliv2.zip"
                            unzip -q -o awscliv2.zip
                            $SUDO ./aws/install -i "${ORB_VAL_INSTALL_DIR}" -b "${ORB_VAL_BINARY_DIR}"
                            rm -r awscliv2.zip ./aws
                            ;;
                        linux_alpine)
                            apk --no-cache add \
                                binutils \
                                curl

                            curl -L https://alpine-pkgs.sgerrand.com/sgerrand.rsa.pub -o /etc/apk/keys/sgerrand.rsa.pub
                            curl -LO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.34-r0/glibc-2.34-r0.apk   
                            curl -LO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.34-r0/glibc-bin-2.34-r0.apk
                            curl -LO https://github.com/sgerrand/alpine-pkg-glibc/releases/download/2.34-r0/glibc-i18n-2.34-r0.apk

                            apk add --force-overwrite --no-cache \
                                glibc-2.34-r0.apk \
                                glibc-bin-2.34-r0.apk \
                                glibc-i18n-2.34-r0.apk

                            /usr/glibc-compat/bin/localedef -i en_US -f UTF-8 en_US.UTF-8
                            curl -sSL "https://awscli.amazonaws.com/awscli-exe-linux-x86_64$1.zip" -o "awscliv2.zip"

                            echo "https://awscli.amazonaws.com/awscli-exe-linux-x86_64$1.zip"
                            unzip awscliv2.zip
                            aws/install
                            rm -r awscliv2.zip ./aws
                            ;;
                        *)
                            echo "This orb does not currently support your platform. If you believe it should, please consider opening an issue on the GitHub repository:"
                            echo "https://github.com/CircleCI-Public/aws-cli-orb/issues/new"
                            exit 1
                            ;;
                        esac
                        # Toggle AWS Pager
                        if [ "$ORB_VAL_DISABLE_PAGER" = 1 ]; then
                            if [ -z "${AWS_PAGER+x}" ]; then
                                echo 'export AWS_PAGER=""' >>"$BASH_ENV"
                                echo "AWS_PAGER is being set to the empty string to disable all output paging for AWS CLI commands."
                                echo "You can set the 'disable-aws-pager' parameter to 'false' to disable this behavior."       
                            fi
                        fi
                    }

                    Uninstall_AWS_CLI() {
                        if uname -a | grep "x86_64 Msys"; then
                            if [ ! "$(command -v choco)" ]; then
                                echo "Chocolatey is required to uninstall AWS"
                                exit 1
                            fi
                            choco uninstall awscli
                        else
                            AWS_CLI_PATH=$(command -v aws)
                            echo "$AWS_CLI_PATH"
                            if [ -n "$AWS_CLI_PATH" ]; then
                                EXISTING_AWS_VERSION=$(aws --version)
                                echo "Uninstalling ${EXISTING_AWS_VERSION}"
                                # shellcheck disable=SC2012
                                if [ -L "$AWS_CLI_PATH" ]; then
                                    AWS_SYMLINK_PATH=$(ls -l "$AWS_CLI_PATH" | sed -e 's/.* -> //')
                                fi
                                if uname -a | grep "x86_64 Msys"; then export SUDO=""; fi
                                $SUDO rm -rf "$AWS_CLI_PATH" "$AWS_SYMLINK_PATH" "$HOME/.aws/" "/usr/local/bin/aws" "/usr/local/bin/aws_completer" "/usr/local/aws-cli"
                            else
                                echo "No AWS install found"
                            fi
                        fi
                    }

                    if [ ! "$(command -v aws)" ]; then
                        if [ "$ORB_VAL_AWS_CLI_VERSION" = "latest" ]; then
                            Install_AWS_CLI
                        else
                            if uname -a | grep "x86_64 Msys"; then
                                Install_AWS_CLI "${ORB_VAL_AWS_CLI_VERSION}"
                            else
                                Install_AWS_CLI "-${ORB_VAL_AWS_CLI_VERSION}"
                            fi
                        fi
                    elif [ "$ORB_VAL_OVERRIDE" = 1 ]; then
                        Uninstall_AWS_CLI
                        if uname -a | grep "x86_64 Msys"; then
                            Install_AWS_CLI "${ORB_VAL_AWS_CLI_VERSION}"
                        else
                            Install_AWS_CLI "-${ORB_VAL_AWS_CLI_VERSION}"
                        fi
                    else
                        echo "AWS CLI is already installed, skipping installation."
                        aws --version
                    fi
                environment:
                    ORB_VAL_AWS_CLI_VERSION: <<parameters.version>>
                    ORB_VAL_BINARY_DIR: <<parameters.binary_dir>>
                    ORB_VAL_DISABLE_PAGER: <<parameters.disable_aws_pager>>
                    ORB_VAL_INSTALL_DIR: <<parameters.install_dir>>
                    ORB_VAL_OVERRIDE: <<parameters.override_installed>>
                name: Install AWS CLI - <<parameters.version>>
    role_arn_setup:
        description: |
            Create a new profile with role arn and source profile
        parameters:
            profile_name:
                description: Name of new profile associated with role arn.
                type: string
            role_arn:
                description: Role ARN that the profile should take.
                type: string
            source_profile:
                default: default
                description: Source profile containing credentials to assume the role with role_arn.
                type: string
        steps:
            - run:
                command: |
                    # shellcheck disable=SC2148
                    ORB_EVAL_ROLE_ARN=$(circleci env subst "${ORB_EVAL_ROLE_ARN}")
                    ORB_EVAL_PROFILE_NAME=$(circleci env subst "${ORB_EVAL_PROFILE_NAME}")
                    ORB_EVAL_SOURCE_PROFILE=$(circleci env subst "${ORB_EVAL_SOURCE_PROFILE}")
                    if [ ! -f "${HOME}/.aws/credentials" ]; then
                        echo "Credentials not found. Run setup command before role-arn-setup."
                        exit 1
                    fi

                    aws configure set profile."${ORB_EVAL_PROFILE_NAME}".role_arn "${ORB_EVAL_ROLE_ARN}"
                    aws configure set profile."${ORB_EVAL_PROFILE_NAME}".source_profile "${ORB_EVAL_SOURCE_PROFILE}"
                environment:
                    ORB_EVAL_PROFILE_NAME: <<parameters.profile_name>>
                    ORB_EVAL_ROLE_ARN: <<parameters.role_arn>>
                    ORB_EVAL_SOURCE_PROFILE: <<parameters.source_profile>>
                name: Configure role arn for profile <<parameters.profile_name>>
    setup:
        description: |
            Configure and store AWS credentials in
            ~/.aws/credentials and ~/.aws/config
        parameters:
            aws_access_key_id:
                default: AWS_ACCESS_KEY_ID
                description: |
                    AWS access key id for IAM role. Set this to the name of
                    the environment variable you will use to hold this
                    value, i.e. AWS_ACCESS_KEY.
                type: env_var_name
            aws_secret_access_key:
                default: AWS_SECRET_ACCESS_KEY
                description: |
                    AWS secret key for IAM role. Set this to the name of
                    the environment variable you will use to hold this
                    value, i.e. AWS_SECRET_ACCESS_KEY.
                type: env_var_name
            binary_dir:
                default: /usr/local/bin
                description: |
                    The main aws program in the install directory is symbolically linked to the file aws in the specified path. Defaults to /usr/local/bin
                type: string
            configure_default_region:
                default: true
                description: |
                    Some AWS actions don't require a region; set this to false if you do not want to store a default region in ~/.aws/config
                type: boolean
            configure_profile_region:
                default: true
                description: |
                    Boolean whether to configure the region for the custom (non-default) profile or not
                type: boolean
            disable_aws_pager:
                default: true
                description: |
                    Set to false to skip forceful disabling of all AWS CLI output paging.
                type: boolean
            install_dir:
                default: /usr/local/aws-cli
                description: |
                    Specify the installation directory of AWS CLI. Defaults to /usr/local/aws-cli
                type: string
            override_installed:
                default: false
                description: |
                    By default, if the AWS CLI is detected on the system, the install will be skipped.
                    Enable this to override the installed version and install your specified version.
                type: boolean
            profile_name:
                default: default
                description: Profile name to be configured.
                type: string
            region:
                default: ${AWS_DEFAULT_REGION}
                description: |
                    Env var of AWS region to operate in
                    (defaults to AWS_DEFAULT_REGION)
                type: string
            role_arn:
                default: ""
                description: |
                    The Amazon Resource Name (ARN) of the role that the caller is assuming.
                    Role ARN must be configured for web identity.
                type: string
            role_session_name:
                default: ${CIRCLE_JOB}
                description: An identifier for the assumed role session
                type: string
            session_duration:
                default: "3600"
                description: The duration of the session in seconds
                type: string
            version:
                default: latest
                description: Select a specific version of the AWS v2 CLI. By default the latest version will be used.
                type: string
        steps:
            - install:
                binary_dir: <<parameters.binary_dir>>
                disable_aws_pager: <<parameters.disable_aws_pager>>
                install_dir: <<parameters.install_dir>>
                override_installed: <<parameters.override_installed>>
                version: <<parameters.version>>
            - when:
                condition:
                    and:
                        - <<parameters.role_session_name>>
                        - <<parameters.role_arn>>
                steps:
                    - assume_role_with_web_identity:
                        profile_name: <<parameters.profile_name>>
                        role_arn: <<parameters.role_arn>>
                        role_session_name: <<parameters.role_session_name>>
                        session_duration: <<parameters.session_duration>>
            - run:
                command: "#!/bin/sh\n# shellcheck disable=SC1090\nif grep \"Alpine\" /etc/issue > /dev/null 2>&1; then\n    . \"$BASH_ENV\"\nfi\n\nORB_ENV_ACCESS_KEY_ID=$(circleci env subst \"\\$$ORB_ENV_ACCESS_KEY_ID\")\nORB_ENV_SECRET_ACCESS_KEY=$(circleci env subst \"\\$$ORB_ENV_SECRET_ACCESS_KEY\")\nORB_EVAL_AWS_CLI_REGION=$(circleci env subst \"\\$$ORB_EVAL_AWS_CLI_REGION\")\nORB_EVAL_PROFILE_NAME=$(circleci env subst \"$ORB_EVAL_PROFILE_NAME\")\n\nif [ -z \"$ORB_ENV_ACCESS_KEY_ID\" ] || [ -z \"${ORB_ENV_SECRET_ACCESS_KEY}\" ]; then \n    echo \"Cannot configure profile. AWS access key id and AWS secret access key must be provided.\"\n    exit 1\nfi\n\naws configure set aws_access_key_id \\\n    \"$ORB_ENV_ACCESS_KEY_ID\" \\\n    --profile \"$ORB_EVAL_PROFILE_NAME\"\n\naws configure set aws_secret_access_key \\\n    \"$ORB_ENV_SECRET_ACCESS_KEY\" \\\n    --profile \"$ORB_EVAL_PROFILE_NAME\"\n\nif [ -n \"${AWS_SESSION_TOKEN}\" ]; then\n    aws configure set aws_session_token \\\n        \"${AWS_SESSION_TOKEN}\" \\\n        --profile \"$ORB_EVAL_PROFILE_NAME\"\nfi\n\nif [ \"$ORB_VAL_CONFIG_DEFAULT_REGION\" = \"1\" ]; then\n    aws configure set default.region \"$ORB_EVAL_AWS_CLI_REGION\" \\\n        --profile \"$ORB_EVAL_PROFILE_NAME\"\nfi\n\nif [ \"$ORB_VAL_CONFIG_PROFILE_REGION\" = \"1\" ]; then\n    aws configure set region \"$ORB_EVAL_AWS_CLI_REGION\" \\\n        --profile \"$ORB_EVAL_PROFILE_NAME\"\nfi\n"
                environment:
                    ORB_ENV_ACCESS_KEY_ID: <<parameters.aws_access_key_id>>
                    ORB_ENV_SECRET_ACCESS_KEY: <<parameters.aws_secret_access_key>>
                    ORB_EVAL_AWS_CLI_REGION: <<parameters.region>>
                    ORB_EVAL_PROFILE_NAME: <<parameters.profile_name>>
                    ORB_VAL_CONFIG_DEFAULT_REGION: <<parameters.configure_default_region>>
                    ORB_VAL_CONFIG_PROFILE_REGION: <<parameters.configure_profile_region>>
                name: Configure AWS Access Key ID
executors:
    default:
        description: |
            Highly cached minimal Ubuntu docker designed for CircleCI with Python and NodeJS installed.
        docker:
            - image: cimg/base:<<parameters.tag>>
        parameters:
            tag:
                default: current
                description: |
                    Select your python version or any of the available tags here: https://hub.docker.com/r/cimg/python.
                type: string
examples:
    configure_role_arn:
        description: Configure a new profile to assume a role defined by a role_arn.
        usage:
            version: "2.1"
            orbs:
                aws-cli: circleci/aws-cli@3.1
            jobs:
                configure_role_arn:
                    executor: aws-cli/default
                    steps:
                        - checkout
                        - aws-cli/setup:
                            profile_name: default
                        - aws-cli/role_arn_setup:
                            profile_name: new-profile
                            role_arn: arn:aws:iam::123456789012:role/example-role
                            source_profile: default
                        - run: aws sts assume-role --role_arn "arn:aws:iam::123456789012:role/example-role" --role_session_name AWSCLI-Session
            workflows:
                aws-cli:
                    jobs:
                        - configure_role_arn
    install_aws_cli:
        description: Easily install and configure the AWS CLI automatically in your jobs or commands.
        usage:
            version: "2.1"
            orbs:
                aws-cli: circleci/aws-cli@3.1
            jobs:
                aws-cli-example:
                    executor: aws-cli/default
                    steps:
                        - checkout
                        - aws-cli/setup:
                            profile_name: example
                        - run: echo "Run your code here"
            workflows:
                aws-cli:
                    jobs:
                        - aws-cli-example:
                            context: aws
    install_aws_cli_with_web_identity:
        description: |
            Setup the AWS CLI and configure with Web Identity.
            Assume roles on AWS without storing keys on CircleCI and utilize short-term credentials instead.
            For more information, see the CircleCI OIDC docs: https://circleci.com/docs/2.0/openid-connect-tokens
        usage:
            version: "2.1"
            orbs:
                aws-cli: circleci/aws-cli@3.1
            jobs:
                aws-cli-example:
                    executor: aws-cli/default
                    steps:
                        - checkout
                        - aws-cli/setup:
                            profile_name: WEB IDENTITY PROFILE
                            role_arn: arn:aws:iam::123456789012:role/WEB-IDENTITY-ROLE
                            role_session_name: example-session
                        - run: echo "Run your code here"
            workflows:
                aws-cli:
                    jobs:
                        - aws-cli-example:
                            context: aws

注意点 Nodeのインストール

AWs CLI用Orbは上記のOrb用設定ファイルを見るとPythonが前提として構築されています。このためNodeをインストールする必要があるのですがroot権限やsudoが存在していないため少し書式が異なっています。

Orb利用前
      - run:
          name: "Set up Node.js environment"
          command: |
            npm install
Orb利用中
 - run:
          name: "Install Node.js 18 (binary)"
          command: |
            curl -fsSL https://nodejs.org/dist/v18.20.2/node-v18.20.2-linux-x64.tar.xz -o node.tar.xz
            mkdir -p /tmp/node
            tar -xf node.tar.xz -C /tmp/node --strip-components=1
            echo 'export PATH="/tmp/node/bin:$PATH"' >> $BASH_ENV
            source $BASH_ENV
            node -v
            npm -v

      # npm install
      - run:
          name: "Install dependencies"
          command: |
            source $BASH_ENV
            npm install

このように /tmp 配下にNode.jsを展開して PATH を通すことで、任意バージョンをroot権限なしで利用可能になります。

あらかじめ自作のOrbを準備しておくことでAWS CLI + Node用Orbを整備し再利用することで、config.ymlの書式をよりシンプルに保ち再利用を行うことが可能です。これは機会があればまた触れたいと思います。

Discussion