mirror of
				https://github.com/docker/login-action.git
				synced 2025-10-31 10:10:09 +08:00 
			
		
		
		
	raw authentication to registries
Signed-off-by: CrazyMax <1951866+crazy-max@users.noreply.github.com>
This commit is contained in:
		
							parent
							
								
									bdf14dc173
								
							
						
					
					
						commit
						9fc23e88e3
					
				
							
								
								
									
										70
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										70
									
								
								.github/workflows/ci.yml
									
									
									
									
										vendored
									
									
								
							| @ -286,3 +286,73 @@ jobs: | |||||||
|           registry: gcr.io |           registry: gcr.io | ||||||
|           username: _json_key |           username: _json_key | ||||||
|           password: ${{ secrets.GCR_JSON_KEY }} |           password: ${{ secrets.GCR_JSON_KEY }} | ||||||
|  | 
 | ||||||
|  |   registry-auth: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - | ||||||
|  |         name: Checkout | ||||||
|  |         uses: actions/checkout@v5 | ||||||
|  |       - | ||||||
|  |         name: Login to registries | ||||||
|  |         uses: ./ | ||||||
|  |         with: | ||||||
|  |           registry-auth: | | ||||||
|  |             - username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||||
|  |               password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||||
|  |             - registry: ghcr.io | ||||||
|  |               username: ${{ github.actor }} | ||||||
|  |               password: ${{ secrets.GITHUB_TOKEN }} | ||||||
|  |             - registry: public.ecr.aws | ||||||
|  |               username: ${{ secrets.AWS_ACCESS_KEY_ID }} | ||||||
|  |               password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | ||||||
|  |             - registry: registry.gitlab.com | ||||||
|  |               username: ${{ secrets.GITLAB_USERNAME }} | ||||||
|  |               password: ${{ secrets.GITLAB_TOKEN }} | ||||||
|  | 
 | ||||||
|  |   registry-auth-dup: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - | ||||||
|  |         name: Checkout | ||||||
|  |         uses: actions/checkout@v5 | ||||||
|  |       - | ||||||
|  |         name: Login to registries | ||||||
|  |         uses: ./ | ||||||
|  |         with: | ||||||
|  |           registry-auth: | | ||||||
|  |             - registry: ghcr.io | ||||||
|  |               username: ${{ github.actor }} | ||||||
|  |               password: ${{ secrets.GITHUB_TOKEN }} | ||||||
|  |             - registry: public.ecr.aws | ||||||
|  |               username: ${{ secrets.AWS_ACCESS_KEY_ID }} | ||||||
|  |               password: ${{ secrets.AWS_SECRET_ACCESS_KEY }} | ||||||
|  |             - registry: ghcr.io | ||||||
|  |               username: ${{ github.actor }} | ||||||
|  |               password: ${{ secrets.GITHUB_TOKEN }} | ||||||
|  | 
 | ||||||
|  |   registry-auth-exclusive: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - | ||||||
|  |         name: Checkout | ||||||
|  |         uses: actions/checkout@v5 | ||||||
|  |       - | ||||||
|  |         name: Login to registries | ||||||
|  |         id: login | ||||||
|  |         continue-on-error: true | ||||||
|  |         uses: ./ | ||||||
|  |         with: | ||||||
|  |           registry: ghcr.io | ||||||
|  |           username: ${{ github.actor }} | ||||||
|  |           password: ${{ secrets.GITHUB_TOKEN }} | ||||||
|  |           registry-auth: | | ||||||
|  |             - username: ${{ secrets.DOCKERHUB_USERNAME }} | ||||||
|  |               password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||||
|  |       - | ||||||
|  |         name: Check | ||||||
|  |         run: | | ||||||
|  |           if [ "${{ steps.login.outcome }}" != "failure" ] || [ "${{ steps.login.conclusion }}" != "success" ]; then | ||||||
|  |             echo "::error::Should have failed" | ||||||
|  |             exit 1 | ||||||
|  |           fi | ||||||
|  | |||||||
							
								
								
									
										82
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										82
									
								
								README.md
									
									
									
									
									
								
							| @ -24,6 +24,7 @@ ___ | |||||||
|   * [OCI Oracle Cloud Infrastructure Registry (OCIR)](#oci-oracle-cloud-infrastructure-registry-ocir) |   * [OCI Oracle Cloud Infrastructure Registry (OCIR)](#oci-oracle-cloud-infrastructure-registry-ocir) | ||||||
|   * [Quay.io](#quayio) |   * [Quay.io](#quayio) | ||||||
|   * [DigitalOcean](#digitalocean-container-registry) |   * [DigitalOcean](#digitalocean-container-registry) | ||||||
|  |   * [Authenticate to multiple registries](#authenticate-to-multiple-registries) | ||||||
| * [Customizing](#customizing) | * [Customizing](#customizing) | ||||||
|   * [inputs](#inputs) |   * [inputs](#inputs) | ||||||
| * [Contributing](#contributing) | * [Contributing](#contributing) | ||||||
| @ -494,19 +495,86 @@ jobs: | |||||||
|           password: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }} |           password: ${{ secrets.DIGITALOCEAN_ACCESS_TOKEN }} | ||||||
| ``` | ``` | ||||||
| 
 | 
 | ||||||
|  | ### Authenticate to multiple registries | ||||||
|  | 
 | ||||||
|  | To authenticate against multiple registries, you can specify the login-action | ||||||
|  | step multiple times in your workflow: | ||||||
|  | 
 | ||||||
|  | ```yaml | ||||||
|  | name: ci | ||||||
|  | 
 | ||||||
|  | on: | ||||||
|  |   push: | ||||||
|  |     branches: main | ||||||
|  | 
 | ||||||
|  | jobs: | ||||||
|  |   login: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - | ||||||
|  |         name: Login to Docker Hub | ||||||
|  |         uses: docker/login-action@v3 | ||||||
|  |         with: | ||||||
|  |           username: ${{ vars.DOCKERHUB_USERNAME }} | ||||||
|  |           password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||||
|  |       - | ||||||
|  |         name: Login to GitHub Container Registry | ||||||
|  |         uses: docker/login-action@v3 | ||||||
|  |         with: | ||||||
|  |           registry: ghcr.io | ||||||
|  |           username: ${{ github.actor }} | ||||||
|  |           password: ${{ secrets.GITHUB_TOKEN }} | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
|  | You can also use the `registry-auth` input for raw authentication to | ||||||
|  | registries, defined as YAML objects. Each object can contain `registry`, | ||||||
|  | `username`, `password` and `ecr` keys similar to current inputs: | ||||||
|  | 
 | ||||||
|  | > [!WARNING] | ||||||
|  | > We don't recommend using this method, it's better to use the action multiple | ||||||
|  | > times as shown above. | ||||||
|  | 
 | ||||||
|  | ```yaml | ||||||
|  | name: ci | ||||||
|  | 
 | ||||||
|  | on: | ||||||
|  |   push: | ||||||
|  |     branches: main | ||||||
|  | 
 | ||||||
|  | jobs: | ||||||
|  |   login: | ||||||
|  |     runs-on: ubuntu-latest | ||||||
|  |     steps: | ||||||
|  |       - | ||||||
|  |         name: Login to registries | ||||||
|  |         uses: docker/login-action@v3 | ||||||
|  |         with: | ||||||
|  |           registry-auth: | | ||||||
|  |             - username: ${{ vars.DOCKERHUB_USERNAME }} | ||||||
|  |               password: ${{ secrets.DOCKERHUB_TOKEN }} | ||||||
|  |             - registry: ghcr.io | ||||||
|  |               username: ${{ github.actor }} | ||||||
|  |               password: ${{ secrets.GITHUB_TOKEN }} | ||||||
|  | ``` | ||||||
|  | 
 | ||||||
| ## Customizing | ## Customizing | ||||||
| 
 | 
 | ||||||
| ### inputs | ### inputs | ||||||
| 
 | 
 | ||||||
| The following inputs can be used as `step.with` keys: | The following inputs can be used as `step.with` keys: | ||||||
| 
 | 
 | ||||||
| | Name       | Type   | Default | Description                                                                   | | | Name            | Type   | Default     | Description                                                                   | | ||||||
| |------------|--------|---------|-------------------------------------------------------------------------------| | |-----------------|--------|-------------|-------------------------------------------------------------------------------| | ||||||
| | `registry` | String |         | Server address of Docker registry. If not set then will default to Docker Hub | | | `registry`      | String | `docker.io` | Server address of Docker registry. If not set then will default to Docker Hub | | ||||||
| | `username` | String |         | Username for authenticating to the Docker registry                            | | | `username`      | String |             | Username for authenticating to the Docker registry                            | | ||||||
| | `password` | String |         | Password or personal access token for authenticating the Docker registry      | | | `password`      | String |             | Password or personal access token for authenticating the Docker registry      | | ||||||
| | `ecr`      | String | `auto`  | Specifies whether the given registry is ECR (`auto`, `true` or `false`)       | | | `ecr`           | String | `auto`      | Specifies whether the given registry is ECR (`auto`, `true` or `false`)       | | ||||||
| | `logout`   | Bool   | `true`  | Log out from the Docker registry at the end of a job                          | | | `logout`        | Bool   | `true`      | Log out from the Docker registry at the end of a job                          | | ||||||
|  | | `registry-auth` | YAML   |             | Raw authentication to registries, defined as YAML objects                     | | ||||||
|  | 
 | ||||||
|  | > [!NOTE] | ||||||
|  | > The `registry-auth` input is mutually exclusive with `registry`, `username`, | ||||||
|  | > `password` and `ecr` inputs. | ||||||
| 
 | 
 | ||||||
| ## Contributing | ## Contributing | ||||||
| 
 | 
 | ||||||
|  | |||||||
| @ -18,12 +18,14 @@ inputs: | |||||||
|     required: false |     required: false | ||||||
|   ecr: |   ecr: | ||||||
|     description: 'Specifies whether the given registry is ECR (auto, true or false)' |     description: 'Specifies whether the given registry is ECR (auto, true or false)' | ||||||
|     default: 'auto' |  | ||||||
|     required: false |     required: false | ||||||
|   logout: |   logout: | ||||||
|     description: 'Log out from the Docker registry at the end of a job' |     description: 'Log out from the Docker registry at the end of a job' | ||||||
|     default: 'true' |     default: 'true' | ||||||
|     required: false |     required: false | ||||||
|  |   registry-auth: | ||||||
|  |     description: 'Raw authentication to registries, defined as YAML objects' | ||||||
|  |     required: false | ||||||
| 
 | 
 | ||||||
| runs: | runs: | ||||||
|   using: 'node20' |   using: 'node20' | ||||||
|  | |||||||
| @ -30,9 +30,11 @@ | |||||||
|     "@aws-sdk/client-ecr-public": "^3.859.0", |     "@aws-sdk/client-ecr-public": "^3.859.0", | ||||||
|     "@docker/actions-toolkit": "^0.62.1", |     "@docker/actions-toolkit": "^0.62.1", | ||||||
|     "http-proxy-agent": "^7.0.2", |     "http-proxy-agent": "^7.0.2", | ||||||
|     "https-proxy-agent": "^7.0.6" |     "https-proxy-agent": "^7.0.6", | ||||||
|  |     "js-yaml": "^4.1.0" | ||||||
|   }, |   }, | ||||||
|   "devDependencies": { |   "devDependencies": { | ||||||
|  |     "@types/js-yaml": "^4.0.9", | ||||||
|     "@types/node": "^20.12.12", |     "@types/node": "^20.12.12", | ||||||
|     "@typescript-eslint/eslint-plugin": "^7.9.0", |     "@typescript-eslint/eslint-plugin": "^7.9.0", | ||||||
|     "@typescript-eslint/parser": "^7.9.0", |     "@typescript-eslint/parser": "^7.9.0", | ||||||
|  | |||||||
| @ -6,6 +6,7 @@ export interface Inputs { | |||||||
|   password: string; |   password: string; | ||||||
|   ecr: string; |   ecr: string; | ||||||
|   logout: boolean; |   logout: boolean; | ||||||
|  |   registryAuth: string; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function getInputs(): Inputs { | export function getInputs(): Inputs { | ||||||
| @ -14,6 +15,7 @@ export function getInputs(): Inputs { | |||||||
|     username: core.getInput('username'), |     username: core.getInput('username'), | ||||||
|     password: core.getInput('password'), |     password: core.getInput('password'), | ||||||
|     ecr: core.getInput('ecr'), |     ecr: core.getInput('ecr'), | ||||||
|     logout: core.getBooleanInput('logout') |     logout: core.getBooleanInput('logout'), | ||||||
|  |     registryAuth: core.getInput('registry-auth') | ||||||
|   }; |   }; | ||||||
| } | } | ||||||
|  | |||||||
| @ -36,11 +36,7 @@ export async function loginStandard(registry: string, username: string, password | |||||||
|   loginArgs.push('--username', username); |   loginArgs.push('--username', username); | ||||||
|   loginArgs.push(registry); |   loginArgs.push(registry); | ||||||
| 
 | 
 | ||||||
|   if (registry) { |   core.info(`Logging into ${registry}...`); | ||||||
|     core.info(`Logging into ${registry}...`); |  | ||||||
|   } else { |  | ||||||
|     core.info(`Logging into Docker Hub...`); |  | ||||||
|   } |  | ||||||
|   await Docker.getExecOutput(loginArgs, { |   await Docker.getExecOutput(loginArgs, { | ||||||
|     ignoreReturnCode: true, |     ignoreReturnCode: true, | ||||||
|     silent: true, |     silent: true, | ||||||
|  | |||||||
							
								
								
									
										50
									
								
								src/main.ts
									
									
									
									
									
								
							
							
						
						
									
										50
									
								
								src/main.ts
									
									
									
									
									
								
							| @ -1,21 +1,61 @@ | |||||||
|  | import * as yaml from 'js-yaml'; | ||||||
|  | import * as core from '@actions/core'; | ||||||
| import * as actionsToolkit from '@docker/actions-toolkit'; | import * as actionsToolkit from '@docker/actions-toolkit'; | ||||||
| 
 | 
 | ||||||
| import * as context from './context'; | import * as context from './context'; | ||||||
| import * as docker from './docker'; | import * as docker from './docker'; | ||||||
| import * as stateHelper from './state-helper'; | import * as stateHelper from './state-helper'; | ||||||
| 
 | 
 | ||||||
|  | interface Auth { | ||||||
|  |   registry: string; | ||||||
|  |   username: string; | ||||||
|  |   password: string; | ||||||
|  |   ecr: string; | ||||||
|  | } | ||||||
|  | 
 | ||||||
| export async function main(): Promise<void> { | export async function main(): Promise<void> { | ||||||
|   const input: context.Inputs = context.getInputs(); |   const inputs: context.Inputs = context.getInputs(); | ||||||
|   stateHelper.setRegistry(input.registry); |   stateHelper.setLogout(inputs.logout); | ||||||
|   stateHelper.setLogout(input.logout); | 
 | ||||||
|   await docker.login(input.registry, input.username, input.password, input.ecr); |   if (inputs.registryAuth && (inputs.registry || inputs.username || inputs.password || inputs.ecr)) { | ||||||
|  |     throw new Error('Cannot use registry-auth with other inputs'); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   if (!inputs.registryAuth) { | ||||||
|  |     stateHelper.setRegistries([inputs.registry || 'docker.io']); | ||||||
|  |     await docker.login(inputs.registry || 'docker.io', inputs.username, inputs.password, inputs.ecr || 'auto'); | ||||||
|  |     return; | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const auths = yaml.load(inputs.registryAuth) as Auth[]; | ||||||
|  |   if (auths.length == 0) { | ||||||
|  |     throw new Error('No registry to login'); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   const registries: string[] = []; | ||||||
|  |   for (const auth of auths) { | ||||||
|  |     if (!auth.registry) { | ||||||
|  |       registries.push('docker.io'); | ||||||
|  |     } else { | ||||||
|  |       registries.push(auth.registry); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  |   stateHelper.setRegistries(registries.filter((value, index, self) => self.indexOf(value) === index)); | ||||||
|  | 
 | ||||||
|  |   for (const auth of auths) { | ||||||
|  |     await core.group(`Login to ${auth.registry || 'docker.io'}`, async () => { | ||||||
|  |       await docker.login(auth.registry || 'docker.io', auth.username, auth.password, auth.ecr || 'auto'); | ||||||
|  |     }); | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| async function post(): Promise<void> { | async function post(): Promise<void> { | ||||||
|   if (!stateHelper.logout) { |   if (!stateHelper.logout) { | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|   await docker.logout(stateHelper.registry); |   for (const registry of stateHelper.registries.split(',')) { | ||||||
|  |     await docker.logout(registry); | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| actionsToolkit.run(main, post); | actionsToolkit.run(main, post); | ||||||
|  | |||||||
| @ -1,10 +1,10 @@ | |||||||
| import * as core from '@actions/core'; | import * as core from '@actions/core'; | ||||||
| 
 | 
 | ||||||
| export const registry = process.env['STATE_registry'] || ''; | export const registries = process.env['STATE_registries'] || ''; | ||||||
| export const logout = /true/i.test(process.env['STATE_logout'] || ''); | export const logout = /true/i.test(process.env['STATE_logout'] || ''); | ||||||
| 
 | 
 | ||||||
| export function setRegistry(registry: string) { | export function setRegistries(registries: string[]) { | ||||||
|   core.saveState('registry', registry); |   core.saveState('registries', registries.join(',')); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export function setLogout(logout: boolean) { | export function setLogout(logout: boolean) { | ||||||
|  | |||||||
| @ -3236,6 +3236,13 @@ __metadata: | |||||||
|   languageName: node |   languageName: node | ||||||
|   linkType: hard |   linkType: hard | ||||||
| 
 | 
 | ||||||
|  | "@types/js-yaml@npm:^4.0.9": | ||||||
|  |   version: 4.0.9 | ||||||
|  |   resolution: "@types/js-yaml@npm:4.0.9" | ||||||
|  |   checksum: e5e5e49b5789a29fdb1f7d204f82de11cb9e8f6cb24ab064c616da5d6e1b3ccfbf95aa5d1498a9fbd3b9e745564e69b4a20b6c530b5a8bbb2d4eb830cda9bc69 | ||||||
|  |   languageName: node | ||||||
|  |   linkType: hard | ||||||
|  | 
 | ||||||
| "@types/node-fetch@npm:^2.5.0": | "@types/node-fetch@npm:^2.5.0": | ||||||
|   version: 2.6.4 |   version: 2.6.4 | ||||||
|   resolution: "@types/node-fetch@npm:2.6.4" |   resolution: "@types/node-fetch@npm:2.6.4" | ||||||
| @ -4315,6 +4322,7 @@ __metadata: | |||||||
|     "@aws-sdk/client-ecr": ^3.859.0 |     "@aws-sdk/client-ecr": ^3.859.0 | ||||||
|     "@aws-sdk/client-ecr-public": ^3.859.0 |     "@aws-sdk/client-ecr-public": ^3.859.0 | ||||||
|     "@docker/actions-toolkit": ^0.62.1 |     "@docker/actions-toolkit": ^0.62.1 | ||||||
|  |     "@types/js-yaml": ^4.0.9 | ||||||
|     "@types/node": ^20.12.12 |     "@types/node": ^20.12.12 | ||||||
|     "@typescript-eslint/eslint-plugin": ^7.9.0 |     "@typescript-eslint/eslint-plugin": ^7.9.0 | ||||||
|     "@typescript-eslint/parser": ^7.9.0 |     "@typescript-eslint/parser": ^7.9.0 | ||||||
| @ -4326,6 +4334,7 @@ __metadata: | |||||||
|     http-proxy-agent: ^7.0.2 |     http-proxy-agent: ^7.0.2 | ||||||
|     https-proxy-agent: ^7.0.6 |     https-proxy-agent: ^7.0.6 | ||||||
|     jest: ^29.7.0 |     jest: ^29.7.0 | ||||||
|  |     js-yaml: ^4.1.0 | ||||||
|     prettier: ^3.2.5 |     prettier: ^3.2.5 | ||||||
|     ts-jest: ^29.1.2 |     ts-jest: ^29.1.2 | ||||||
|     ts-node: ^10.9.2 |     ts-node: ^10.9.2 | ||||||
|  | |||||||
		Loading…
	
		Reference in New Issue
	
	Block a user
	 CrazyMax
						CrazyMax