@@ -16,6 +16,7 @@ limitations under the License.
1616import fs from 'node:fs' ;
1717import os from 'node:os' ;
1818import path from 'node:path' ;
19+ import { execFileSync } from 'node:child_process' ;
1920import { parseImageName } from './name' ;
2021
2122export type Credentials = {
@@ -24,32 +25,21 @@ export type Credentials = {
2425} ;
2526
2627type DockerConifg = {
27- auths ?: { [ registry : string ] : { auth : string ; identitytoken ?: string } } ;
28+ credsStore ?: string ,
29+ auths ?: { [ registry : string ] : { auth : string ; identitytoken ?: string } } ,
30+ credHelpers ?: { [ registry : string ] : string } ,
2831} ;
2932
3033// Returns the credentials for a given registry by reading the Docker config
31- // file.
32- export const getRegistryCredentials = ( imageName : string ) : Credentials => {
33- const { registry } = parseImageName ( imageName ) ;
34- const dockerConfigFile = path . join ( os . homedir ( ) , '.docker' , 'config.json' ) ;
35-
36- let content : string | undefined ;
37- try {
38- content = fs . readFileSync ( dockerConfigFile , 'utf8' ) ;
39- } catch ( err ) {
40- throw new Error ( `No credential file found at ${ dockerConfigFile } ` ) ;
41- }
42-
43- const dockerConfig : DockerConifg = JSON . parse ( content ) ;
44-
34+ function credentialFromAuths ( dockerConfig : DockerConifg , registry : string ) {
4535 const credKey =
4636 Object . keys ( dockerConfig ?. auths || { } ) . find ( ( key ) =>
4737 key . includes ( registry )
4838 ) || registry ;
4939 const creds = dockerConfig ?. auths ?. [ credKey ] ;
5040
5141 if ( ! creds ) {
52- throw new Error ( `No credentials found for registry ${ registry } ` ) ;
42+ return null ;
5343 }
5444
5545 // Extract username/password from auth string
@@ -59,6 +49,74 @@ export const getRegistryCredentials = (imageName: string): Credentials => {
5949 const pass = creds . identitytoken ? creds . identitytoken : password ;
6050
6151 return { username, password : pass } ;
52+ }
53+
54+ function credentialFromCredHelpers ( dockerConfig : DockerConifg , registry : string ) {
55+ // Check if the registry has a credHelper and use it if it does
56+ const helper = dockerConfig ?. credHelpers ?. [ registry ] ;
57+
58+ if ( ! helper ) {
59+ return null ;
60+ }
61+
62+ return launchHelper ( helper , registry ) ;
63+ }
64+
65+ function credentialFromCredsStore ( dockerConfig : DockerConifg , registry : string ) {
66+ // If the credsStore is set, use it to get the credentials
67+ const helper = dockerConfig ?. credsStore ;
68+
69+ if ( ! helper ) {
70+ return null ;
71+ }
72+
73+ return launchHelper ( helper , registry ) ;
74+ }
75+
76+ function launchHelper ( helper : string , registry : string ) {
77+ // Get the credentials from the helper.
78+ // Parameter for helper is 'get' and registry is passed as input
79+ // The helper should return a JSON object with the keys "Username" and "Secret"
80+ try {
81+ const output = execFileSync ( `docker-credential-${ helper } ` , [ "get" ] , {
82+ input : registry ,
83+ } ) . toString ( ) ;
84+
85+ const { Username : username , Secret : password } = JSON . parse ( output ) ;
86+
87+ return { username, password } ;
88+ } catch ( err ) {
89+ throw new Error ( `Failed to get credentials from helper ${ helper } for registry ${ registry } : ${ err } ` ) ;
90+ }
91+ }
92+
93+ // file.
94+ export const getRegistryCredentials = ( imageName : string ) : Credentials => {
95+ const { registry } = parseImageName ( imageName ) ;
96+ const dockerConfigFile = path . join ( os . homedir ( ) , '.docker' , 'config.json' ) ;
97+
98+ let content : string | undefined ;
99+ try {
100+ content = fs . readFileSync ( dockerConfigFile , 'utf8' ) ;
101+ } catch ( err ) {
102+ throw new Error ( `No credential file found at ${ dockerConfigFile } ` ) ;
103+ }
104+
105+ const dockerConfig : DockerConifg = JSON . parse ( content ) ;
106+
107+ const fromAuths = credentialFromAuths ( dockerConfig , registry ) ;
108+ if ( fromAuths ) {
109+ return fromAuths ;
110+ }
111+ const fromCredHelpers = credentialFromCredHelpers ( dockerConfig , registry ) ;
112+ if ( fromCredHelpers ) {
113+ return fromCredHelpers ;
114+ }
115+ const fromCredsStore = credentialFromCredsStore ( dockerConfig , registry ) ;
116+ if ( fromCredsStore ) {
117+ return fromCredsStore ;
118+ }
119+ throw new Error ( `No credentials found for registry ${ registry } ` ) ;
62120} ;
63121
64122// Encode the username and password as base64-encoded basicauth value
0 commit comments