diff --git a/.github/workflows/test.yaml b/.github/workflows/test.yaml index baba103e..85aad2ed 100644 --- a/.github/workflows/test.yaml +++ b/.github/workflows/test.yaml @@ -13,35 +13,34 @@ concurrency: cancel-in-progress: true jobs: - install_and_compile: - name: 'install_and_compile' - runs-on: 'ubuntu-latest' - steps: - - uses: 'actions/checkout@v2' - - - uses: 'actions/setup-node@v2' - with: - node-version: '12.x' - - - name: 'npm ci' - run: 'npm ci' - - - name: 'npm build' - run: 'npm run build' - - - name: 'verify compiled' - shell: 'bash' - run: |- - if [ -n "$(git status --porcelain)" ]; then - echo "TypeScript is not compiled!" - git diff - exit 1 - fi - - - unit: - name: 'unit' - needs: install_and_compile + # install_and_compile: + # name: 'install_and_compile' + # runs-on: 'ubuntu-latest' + # steps: + # - uses: 'actions/checkout@v2' + + # - uses: 'actions/setup-node@v2' + # with: + # node-version: '12.x' + + # - name: 'npm ci' + # run: 'npm ci' + + # - name: 'npm build' + # run: 'npm run build' + + # - name: 'verify compiled' + # shell: 'bash' + # run: |- + # if [ -n "$(git status --porcelain)" ]; then + # echo "TypeScript is not compiled!" + # git diff + # exit 1 + # fi + + + experiment1: + name: 'experiment1' runs-on: 'ubuntu-latest' steps: @@ -51,27 +50,15 @@ jobs: with: node-version: '12.x' - - name: 'npm ci' - run: 'npm ci' - - - name: 'npm lint' - run: 'npm run lint' - - - name: 'npm test' - run: 'npm run test' - + - id: 'auth-default' + name: 'auth-default' + uses: './' + with: + credentials_json: '' - credentials_json: - name: 'credentials_json' - needs: install_and_compile - runs-on: '${{ matrix.os }}' - strategy: - fail-fast: false - matrix: - os: - - 'ubuntu-latest' - - 'windows-latest' - - 'macos-latest' + experiment2: + name: 'experiment2' + runs-on: 'ubuntu-latest' steps: - uses: 'actions/checkout@v2' @@ -83,60 +70,10 @@ jobs: - id: 'auth-default' name: 'auth-default' uses: './' - with: - credentials_json: '${{ secrets.AUTH_SA_KEY_JSON }}' - - - id: 'setup-gcloud' - name: 'setup-gcloud' - uses: 'google-github-actions/setup-gcloud@master' - - - id: 'gcloud' - name: 'gcloud' - shell: 'bash' - run: |- - gcloud secrets versions access "latest" --secret "${{ secrets.OIDC_AUTH_TEST_SECRET_NAME }}" - - id: 'auth-access-token' - name: 'auth-access-token' - uses: './' - with: - credentials_json: '${{ secrets.AUTH_SA_KEY_B64 }}' - token_format: 'access_token' - - - id: 'access-token' - name: 'access-token' - shell: 'bash' - run: |- - curl https://secretmanager.googleapis.com/v1/projects/${{ steps.auth-access-token.outputs.project_id }}/secrets/${{ secrets.OIDC_AUTH_TEST_SECRET_NAME }}/versions/latest:access \ - --silent \ - --show-error \ - --fail \ - --header "Authorization: Bearer ${{ steps.auth-access-token.outputs.access_token }}" - - - id: 'auth-id-token' - name: 'auth-id-token' - uses: './' - with: - credentials_json: '${{ secrets.AUTH_SA_KEY_JSON }}' - token_format: 'id_token' - id_token_audience: 'https://secretmanager.googleapis.com/' - id_token_include_email: true - - - workload_identity_federation: - name: 'workload_identity_federation' - needs: install_and_compile - runs-on: '${{ matrix.os }}' - strategy: - fail-fast: false - matrix: - os: - - 'ubuntu-latest' - - 'windows-latest' - - 'macos-latest' - - permissions: - id-token: 'write' + experiment3: + name: 'experiment3' + runs-on: 'ubuntu-latest' steps: - uses: 'actions/checkout@v2' @@ -149,43 +86,157 @@ jobs: name: 'auth-default' uses: './' with: - workload_identity_provider: '${{ secrets.WIF_PROVIDER_NAME }}' - service_account: '${{ secrets.OIDC_AUTH_SA_EMAIL }}' - - - id: 'setup-gcloud' - name: 'setup-gcloud' - uses: 'google-github-actions/setup-gcloud@master' - - - id: 'gcloud' - name: 'gcloud' - shell: 'bash' - run: |- - gcloud secrets versions access "latest" --secret "${{ secrets.OIDC_AUTH_TEST_SECRET_NAME }}" - - - id: 'auth-access-token' - name: 'auth-access-token' - uses: './' - with: - workload_identity_provider: '${{ secrets.WIF_PROVIDER_NAME }}' - service_account: '${{ secrets.OIDC_AUTH_SA_EMAIL }}' - token_format: 'access_token' - - - id: 'access-token' - name: 'access-token' - shell: 'bash' - run: |- - curl https://secretmanager.googleapis.com/v1/projects/${{ steps.auth-access-token.outputs.project_id }}/secrets/${{ secrets.OIDC_AUTH_TEST_SECRET_NAME }}/versions/latest:access \ - --silent \ - --show-error \ - --fail \ - --header "Authorization: Bearer ${{ steps.auth-access-token.outputs.access_token }}" - - - id: 'auth-id-token' - name: 'auth-id-token' - uses: './' - with: - workload_identity_provider: '${{ secrets.WIF_PROVIDER_NAME }}' - service_account: '${{ secrets.OIDC_AUTH_SA_EMAIL }}' - token_format: 'id_token' - id_token_audience: 'https://secretmanager.googleapis.com/' - id_token_include_email: true + credentials_json: ${{secrets.NOT_A_REAL_SECRET}} + + + + # unit: + # name: 'unit' + # needs: install_and_compile + # runs-on: 'ubuntu-latest' + + # steps: + # - uses: 'actions/checkout@v2' + + # - uses: 'actions/setup-node@v2' + # with: + # node-version: '12.x' + + # - name: 'npm ci' + # run: 'npm ci' + + # - name: 'npm lint' + # run: 'npm run lint' + + # - name: 'npm test' + # run: 'npm run test' + + + # credentials_json: + # name: 'credentials_json' + # needs: install_and_compile + # runs-on: '${{ matrix.os }}' + # strategy: + # fail-fast: false + # matrix: + # os: + # - 'ubuntu-latest' + # - 'windows-latest' + # - 'macos-latest' + + # steps: + # - uses: 'actions/checkout@v2' + + # - uses: 'actions/setup-node@v2' + # with: + # node-version: '12.x' + + # - id: 'auth-default' + # name: 'auth-default' + # uses: './' + # with: + # credentials_json: '${{ secrets.AUTH_SA_KEY_JSON }}' + + # - id: 'setup-gcloud' + # name: 'setup-gcloud' + # uses: 'google-github-actions/setup-gcloud@master' + + # - id: 'gcloud' + # name: 'gcloud' + # shell: 'bash' + # run: |- + # gcloud secrets versions access "latest" --secret "${{ secrets.OIDC_AUTH_TEST_SECRET_NAME }}" + + # - id: 'auth-access-token' + # name: 'auth-access-token' + # uses: './' + # with: + # credentials_json: '${{ secrets.AUTH_SA_KEY_B64 }}' + # token_format: 'access_token' + + # - id: 'access-token' + # name: 'access-token' + # shell: 'bash' + # run: |- + # curl https://secretmanager.googleapis.com/v1/projects/${{ steps.auth-access-token.outputs.project_id }}/secrets/${{ secrets.OIDC_AUTH_TEST_SECRET_NAME }}/versions/latest:access \ + # --silent \ + # --show-error \ + # --fail \ + # --header "Authorization: Bearer ${{ steps.auth-access-token.outputs.access_token }}" + + # - id: 'auth-id-token' + # name: 'auth-id-token' + # uses: './' + # with: + # credentials_json: '${{ secrets.AUTH_SA_KEY_JSON }}' + # token_format: 'id_token' + # id_token_audience: 'https://secretmanager.googleapis.com/' + # id_token_include_email: true + + + # workload_identity_federation: + # name: 'workload_identity_federation' + # needs: install_and_compile + # runs-on: '${{ matrix.os }}' + # strategy: + # fail-fast: false + # matrix: + # os: + # - 'ubuntu-latest' + # - 'windows-latest' + # - 'macos-latest' + + # permissions: + # id-token: 'write' + + # steps: + # - uses: 'actions/checkout@v2' + + # - uses: 'actions/setup-node@v2' + # with: + # node-version: '12.x' + + # - id: 'auth-default' + # name: 'auth-default' + # uses: './' + # with: + # workload_identity_provider: '${{ secrets.WIF_PROVIDER_NAME }}' + # service_account: '${{ secrets.OIDC_AUTH_SA_EMAIL }}' + + # - id: 'setup-gcloud' + # name: 'setup-gcloud' + # uses: 'google-github-actions/setup-gcloud@master' + + # - id: 'gcloud' + # name: 'gcloud' + # shell: 'bash' + # run: |- + # gcloud secrets versions access "latest" --secret "${{ secrets.OIDC_AUTH_TEST_SECRET_NAME }}" + + # - id: 'auth-access-token' + # name: 'auth-access-token' + # uses: './' + # with: + # workload_identity_provider: '${{ secrets.WIF_PROVIDER_NAME }}' + # service_account: '${{ secrets.OIDC_AUTH_SA_EMAIL }}' + # token_format: 'access_token' + + # - id: 'access-token' + # name: 'access-token' + # shell: 'bash' + # run: |- + # curl https://secretmanager.googleapis.com/v1/projects/${{ steps.auth-access-token.outputs.project_id }}/secrets/${{ secrets.OIDC_AUTH_TEST_SECRET_NAME }}/versions/latest:access \ + # --silent \ + # --show-error \ + # --fail \ + # --header "Authorization: Bearer ${{ steps.auth-access-token.outputs.access_token }}" + + # - id: 'auth-id-token' + # name: 'auth-id-token' + # uses: './' + # with: + # workload_identity_provider: '${{ secrets.WIF_PROVIDER_NAME }}' + # service_account: '${{ secrets.OIDC_AUTH_SA_EMAIL }}' + # token_format: 'id_token' + # id_token_audience: 'https://secretmanager.googleapis.com/' + # id_token_include_email: true diff --git a/action.yml b/action.yml index 2c3cee49..c29cffdf 100644 --- a/action.yml +++ b/action.yml @@ -52,6 +52,7 @@ inputs: The Google Cloud JSON service account key to use for authentication. This is mutually exclusive with "workload_identity_provider". required: false + default: ~ create_credentials_file: description: |- If true, the action will securely generate a credentials file which can be diff --git a/dist/index.js b/dist/index.js index b71cfc93..c41e1db8 100644 --- a/dist/index.js +++ b/dist/index.js @@ -198,6 +198,25 @@ const workload_identity_client_1 = __webpack_require__(911); const credentials_json_client_1 = __webpack_require__(627); const base_1 = __webpack_require__(843); const utils_1 = __webpack_require__(163); +const util_1 = __webpack_require__(669); +/** + * getInputOK is like getInput in actions/toolkit, but it returns a secondary + * boolean value indicating whether the input was present. The default getInput + * function automatically converts null/undefined to the empty string, so it's + * impossible to differentiate between "unset value" and "value is explicitly + * the empty string". Based on: + * + * https://github.com/actions/toolkit/blob/27f76dfe1afb2b7e5e679cd8e97192d34d8320e6/packages/core/src/core.ts#L128 + * + * @param name Name of the input to retrieve. + */ +function getInputOK(name, options) { + const envName = `INPUT_${name.replace(/ /g, '_').toUpperCase()}`; + const ok = envName in process.env; + const value = core.getInput(name, options); + console.log('process.env', process.env); + return [value, ok]; +} /** * Executes the main action, documented inline. */ @@ -209,10 +228,22 @@ function run() { const workloadIdentityProvider = core.getInput('workload_identity_provider'); const serviceAccount = core.getInput('service_account'); const audience = core.getInput('audience') || `https://iam.googleapis.com/${workloadIdentityProvider}`; - const credentialsJSON = core.getInput('credentials_json'); + // const credentialsJSON = core.getInput('credentials_json'); const createCredentialsFile = core.getBooleanInput('create_credentials_file'); const tokenFormat = core.getInput('token_format'); const delegates = (0, utils_1.explodeStrings)(core.getInput('delegates')); + const [credentialsJSON, hasCredentialsJSON] = getInputOK('credentials_json'); + console.log('credentialsJSON', (0, util_1.inspect)(credentialsJSON)); + console.log('credentialsJSON == null', credentialsJSON == null); + console.log('credentialsJSON === null', credentialsJSON === null); + console.log('credentialsJSON == undefined', credentialsJSON == undefined); + console.log('credentialsJSON === undefined', credentialsJSON === undefined); + console.log('credentialsJSON === ""', credentialsJSON === ''); + console.log('credentialsJSON == ""', credentialsJSON == ''); + console.log('hasCredentialsJSON', hasCredentialsJSON); + if (!credentialsJSON) { + throw new Error('tmp'); + } // Ensure exactly one of workload_identity_provider and credentials_json was // provided. if ((!workloadIdentityProvider && !credentialsJSON) || diff --git a/src/main.ts b/src/main.ts index 2cd58a42..ad297596 100644 --- a/src/main.ts +++ b/src/main.ts @@ -6,6 +6,28 @@ import { CredentialsJSONClient } from './client/credentials_json_client'; import { AuthClient } from './client/auth_client'; import { BaseClient } from './base'; import { explodeStrings } from './utils'; +import { inspect } from 'util'; + +/** + * getInputOK is like getInput in actions/toolkit, but it returns a secondary + * boolean value indicating whether the input was present. The default getInput + * function automatically converts null/undefined to the empty string, so it's + * impossible to differentiate between "unset value" and "value is explicitly + * the empty string". Based on: + * + * https://github.com/actions/toolkit/blob/27f76dfe1afb2b7e5e679cd8e97192d34d8320e6/packages/core/src/core.ts#L128 + * + * @param name Name of the input to retrieve. + */ +function getInputOK(name: string, options?: core.InputOptions): [string, boolean] { + const envName = `INPUT_${name.replace(/ /g, '_').toUpperCase()}`; + const ok = envName in process.env; + const value = core.getInput(name, options); + + console.log('process.env', process.env); + + return [value, ok]; +} /** * Executes the main action, documented inline. @@ -18,11 +40,26 @@ async function run(): Promise { const serviceAccount = core.getInput('service_account'); const audience = core.getInput('audience') || `https://iam.googleapis.com/${workloadIdentityProvider}`; - const credentialsJSON = core.getInput('credentials_json'); + // const credentialsJSON = core.getInput('credentials_json'); const createCredentialsFile = core.getBooleanInput('create_credentials_file'); const tokenFormat = core.getInput('token_format'); const delegates = explodeStrings(core.getInput('delegates')); + const [credentialsJSON, hasCredentialsJSON] = getInputOK('credentials_json'); + + console.log('credentialsJSON', inspect(credentialsJSON)); + console.log('credentialsJSON == null', credentialsJSON == null); + console.log('credentialsJSON === null', credentialsJSON === null); + console.log('credentialsJSON == undefined', credentialsJSON == undefined); + console.log('credentialsJSON === undefined', credentialsJSON === undefined); + console.log('credentialsJSON === ""', credentialsJSON === ''); + console.log('credentialsJSON == ""', credentialsJSON == ''); + console.log('hasCredentialsJSON', hasCredentialsJSON); + + if (!credentialsJSON) { + throw new Error('tmp'); + } + // Ensure exactly one of workload_identity_provider and credentials_json was // provided. if (