Skip to content

Commit

Permalink
fix(docker): use a HEAD request to the real resource auth. (renovateb…
Browse files Browse the repository at this point in the history
  • Loading branch information
vlagorce committed Apr 26, 2022
1 parent b3be29a commit 972b327
Show file tree
Hide file tree
Showing 2 changed files with 107 additions and 44 deletions.
129 changes: 92 additions & 37 deletions lib/modules/datasource/docker/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -105,15 +105,12 @@ describe('modules/datasource/docker/index', () => {
});

describe('getAuthHeaders', () => {
beforeEach(() => {
it('returns "authType token" if both provided', async () => {
httpMock
.scope('https://my.local.registry')
.get('/v2/', undefined, { badheaders: ['authorization'] })
.reply(401, '', { 'www-authenticate': 'Authenticate you must' });
hostRules.hosts.mockReturnValue([]);
});

it('returns "authType token" if both provided', async () => {
hostRules.find.mockReturnValue({
authType: 'some-authType',
token: 'some-token',
Expand All @@ -134,6 +131,11 @@ describe('modules/datasource/docker/index', () => {
});

it('returns "Bearer token" if only token provided', async () => {
httpMock
.scope('https://my.local.registry')
.get('/v2/', undefined, { badheaders: ['authorization'] })
.reply(401, '', { 'www-authenticate': 'Authenticate you must' });
hostRules.hosts.mockReturnValue([]);
hostRules.find.mockReturnValue({
token: 'some-token',
});
Expand All @@ -153,6 +155,11 @@ describe('modules/datasource/docker/index', () => {
});

it('fails', async () => {
httpMock
.scope('https://my.local.registry')
.get('/v2/', undefined, { badheaders: ['authorization'] })
.reply(401, '', { 'www-authenticate': 'Authenticate you must' });
hostRules.hosts.mockReturnValue([]);
httpMock.clear(false);

httpMock
Expand All @@ -168,6 +175,35 @@ describe('modules/datasource/docker/index', () => {

expect(headers).toBeNull();
});

it('use a HEAD request to the real resource and use the auth header values to get a token', async () => {
httpMock
.scope('https://my.local.registry')
.head('/v2/my/node/resource')
.reply(401, '', {
'www-authenticate':
'Bearer realm="https://my.local.registry/oauth2/token",service="my.local.registry",scope="repository:my/node:whatever"',
})
.get(
'/oauth2/token?service=my.local.registry&scope=repository:my/node:whatever'
)
.reply(200, { token: 'some-token' });

const headers = await getAuthHeaders(
http,
'https://my.local.registry',
'my/node/prefix',
'head',
'https://my.local.registry/v2/my/node/resource'
);

// do not inline, otherwise we get false positive from codeql
expect(headers).toMatchInlineSnapshot(`
Object {
"authorization": "Bearer some-token",
}
`);
});
});

describe('getDigest', () => {
Expand Down Expand Up @@ -223,7 +259,7 @@ describe('modules/datasource/docker/index', () => {
.get('/')
.reply(401, '', {
'www-authenticate':
'Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:samalba/my-app:pull "',
'Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:library/some-dep:pull "',
})
.head('/library/some-dep/manifests/latest')
.reply(200, {}, { 'docker-content-digest': 'some-digest' });
Expand All @@ -249,7 +285,7 @@ describe('modules/datasource/docker/index', () => {
.twice()
.reply(401, '', {
'www-authenticate':
'Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:samalba/my-app:pull "',
'Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:library/some-dep:pull "',
})
.head('/library/some-dep/manifests/some-new-value')
.reply(200, undefined, {})
Expand Down Expand Up @@ -497,7 +533,7 @@ describe('modules/datasource/docker/index', () => {
.get('/')
.reply(401, '', {
'www-authenticate':
'Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:samalba/my-app:pull "',
'Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:library/some-other-dep:pull "',
})
.head('/library/some-other-dep/manifests/8.0.0-alpine')
.reply(200, {}, { 'docker-content-digest': 'some-digest' });
Expand Down Expand Up @@ -533,7 +569,7 @@ describe('modules/datasource/docker/index', () => {
it('returns null if no token', async () => {
httpMock
.scope(baseUrl)
.get('/')
.get('/library/node/tags/list?n=10000')
.reply(200, '', {})
.get('/library/node/tags/list?n=10000')
.reply(403);
Expand All @@ -549,7 +585,7 @@ describe('modules/datasource/docker/index', () => {
const tags = ['1.0.0'];
httpMock
.scope('https://registry.company.com/v2')
.get('/')
.get('/node/tags/list?n=10000')
.reply(200, '', {})
.get('/node/tags/list?n=10000')
.reply(
Expand Down Expand Up @@ -580,7 +616,7 @@ describe('modules/datasource/docker/index', () => {
const tags = ['1.0.0'];
httpMock
.scope('https://registry.company.com/v2')
.get('/')
.get('/node/tags/list?n=10000')
.reply(200, '', {})
.get('/node/tags/list?n=10000')
.reply(200, { tags }, {})
Expand Down Expand Up @@ -638,7 +674,7 @@ describe('modules/datasource/docker/index', () => {
it('uses lower tag limit for ECR deps', async () => {
httpMock
.scope(amazonUrl)
.get('/')
.get('/node/tags/list?n=1000')
.reply(200, '', {})
// The tag limit parameter `n` needs to be limited to 1000 for ECR
// See https://docs.aws.amazon.com/AmazonECR/latest/APIReference/API_DescribeRepositories.html#ECR-DescribeRepositories-request-maxResults
Expand All @@ -663,7 +699,7 @@ describe('modules/datasource/docker/index', () => {
it('resolves requests to ECR proxy', async () => {
httpMock
.scope('https://ecr-proxy.company.com/v2')
.get('/')
.get('/node/tags/list?n=10000')
.reply(200, '', {})
.get('/node/tags/list?n=10000')
.reply(
Expand Down Expand Up @@ -727,7 +763,7 @@ describe('modules/datasource/docker/index', () => {

httpMock
.scope('https://ecr-proxy.company.com/v2')
.get('/')
.get('/node/tags/list?n=10000')
.reply(200, '', {})
.get('/node/tags/list?n=10000')
.reply(405, maxResultsErrorBody, {
Expand All @@ -748,7 +784,7 @@ describe('modules/datasource/docker/index', () => {
it('returns null when the response code is not 405', async () => {
httpMock
.scope('https://ecr-proxy.company.com/v2')
.get('/')
.get('/node/tags/list?n=10000')
.reply(200, '', {})
.get('/node/tags/list?n=10000')
.reply(
Expand Down Expand Up @@ -779,7 +815,7 @@ describe('modules/datasource/docker/index', () => {
it('returns null when no response headers are present', async () => {
httpMock
.scope('https://ecr-proxy.company.com/v2')
.get('/')
.get('/node/tags/list?n=10000')
.reply(200, '', {})
.get('/node/tags/list?n=10000')
.reply(405, {
Expand All @@ -802,7 +838,7 @@ describe('modules/datasource/docker/index', () => {
it('returns null when the expected docker header is missing', async () => {
httpMock
.scope('https://ecr-proxy.company.com/v2')
.get('/')
.get('/node/tags/list?n=10000')
.reply(200, '', {})
.get('/node/tags/list?n=10000')
.reply(
Expand Down Expand Up @@ -831,7 +867,7 @@ describe('modules/datasource/docker/index', () => {
it('returns null when the response body does not contain an errors object', async () => {
httpMock
.scope('https://ecr-proxy.company.com/v2')
.get('/')
.get('/node/tags/list?n=10000')
.reply(200, '', {})
.get('/node/tags/list?n=10000')
.reply(
Expand All @@ -852,7 +888,7 @@ describe('modules/datasource/docker/index', () => {
it('returns null when the response body does not contain errors', async () => {
httpMock
.scope('https://ecr-proxy.company.com/v2')
.get('/')
.get('/node/tags/list?n=10000')
.reply(200, '', {})
.get('/node/tags/list?n=10000')
.reply(
Expand All @@ -875,7 +911,7 @@ describe('modules/datasource/docker/index', () => {
it('returns null when the the response errors does not have a message property', async () => {
httpMock
.scope('https://ecr-proxy.company.com/v2')
.get('/')
.get('/node/tags/list?n=10000')
.reply(200, '', {})
.get('/node/tags/list?n=10000')
.reply(
Expand All @@ -902,7 +938,7 @@ describe('modules/datasource/docker/index', () => {
it('returns null when the the error message does not have the expected max results error', async () => {
httpMock
.scope('https://ecr-proxy.company.com/v2')
.get('/')
.get('/node/tags/list?n=10000')
.reply(200, '', {})
.get('/node/tags/list?n=10000')
.reply(
Expand Down Expand Up @@ -932,7 +968,7 @@ describe('modules/datasource/docker/index', () => {
const tags = ['1.0.0'];
httpMock
.scope(baseUrl)
.get('/')
.get('/library/node/tags/list?n=10000')
.reply(401, '', {
'www-authenticate':
'Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:library/node:pull "',
Expand Down Expand Up @@ -960,7 +996,7 @@ describe('modules/datasource/docker/index', () => {
const tags = ['1.0.0'];
httpMock
.scope(baseUrl)
.get('/')
.get('/library/node/tags/list?n=10000')
.reply(401, '', {
'www-authenticate':
'Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:library/node:pull "',
Expand Down Expand Up @@ -988,7 +1024,7 @@ describe('modules/datasource/docker/index', () => {
const tags = ['1.0.0'];
httpMock
.scope('https://k8s.gcr.io/v2/')
.get('/')
.get('/kubernetes-dashboard-amd64/tags/list?n=10000')
.reply(401, '', {
'www-authenticate':
'Bearer realm="https://k8s.gcr.io/v2/token",service="k8s.gcr.io"',
Expand All @@ -1013,7 +1049,7 @@ describe('modules/datasource/docker/index', () => {
it('returns null on error', async () => {
httpMock
.scope(baseUrl)
.get('/')
.get('/my/node/tags/list?n=10000')
.reply(200, null)
.get('/my/node/tags/list?n=10000')
.replyWithError('error');
Expand All @@ -1027,7 +1063,7 @@ describe('modules/datasource/docker/index', () => {
it('strips trailing slash from registry', async () => {
httpMock
.scope(baseUrl)
.get('/')
.get('/my/node/tags/list?n=10000')
.reply(401, '', {
'www-authenticate':
'Bearer realm="https://auth.docker.io/token",service="registry.docker.io",scope="repository:my/node:pull "',
Expand All @@ -1052,9 +1088,12 @@ describe('modules/datasource/docker/index', () => {

it('returns null if no auth', async () => {
hostRules.find.mockReturnValue({});
httpMock.scope(baseUrl).get('/').reply(401, undefined, {
'www-authenticate': 'Basic realm="My Private Docker Registry Server"',
});
httpMock
.scope(baseUrl)
.get('/library/node/tags/list?n=10000')
.reply(401, undefined, {
'www-authenticate': 'Basic realm="My Private Docker Registry Server"',
});
const res = await getPkgReleases({
datasource: DockerDatasource.id,
depName: 'node',
Expand All @@ -1066,7 +1105,9 @@ describe('modules/datasource/docker/index', () => {
httpMock
.scope('https://registry.company.com/v2')
.get('/')
.times(3)
.times(2)
.reply(200)
.get('/node/tags/list?n=10000')
.reply(200)
.get('/node/tags/list?n=10000')
.reply(200, {
Expand Down Expand Up @@ -1129,7 +1170,9 @@ describe('modules/datasource/docker/index', () => {
httpMock
.scope('https://registry.company.com/v2')
.get('/')
.times(4)
.times(3)
.reply(200)
.get('/node/tags/list?n=10000')
.reply(200)
.get('/node/tags/list?n=10000')
.reply(200, { tags: ['abc'] })
Expand Down Expand Up @@ -1169,7 +1212,8 @@ describe('modules/datasource/docker/index', () => {
httpMock
.scope('https://registry.company.com/v2')
.get('/')
.times(2)
.reply(200)
.get('/node/tags/list?n=10000')
.reply(200)
.get('/node/tags/list?n=10000')
.reply(200, { tags: ['latest'] })
Expand All @@ -1193,7 +1237,8 @@ describe('modules/datasource/docker/index', () => {
httpMock
.scope('https://registry.company.com/v2')
.get('/')
.times(2)
.reply(200)
.get('/node/tags/list?n=10000')
.reply(200)
.get('/node/tags/list?n=10000')
.reply(200, { tags: ['latest'] })
Expand All @@ -1216,7 +1261,8 @@ describe('modules/datasource/docker/index', () => {
httpMock
.scope('https://registry.company.com/v2')
.get('/')
.times(2)
.reply(200)
.get('/node/tags/list?n=10000')
.reply(200)
.get('/node/tags/list?n=10000')
.reply(200, { tags: ['latest'] })
Expand All @@ -1236,7 +1282,9 @@ describe('modules/datasource/docker/index', () => {
httpMock
.scope('https://registry.company.com/v2')
.get('/')
.times(4)
.times(3)
.reply(200)
.get('/node/tags/list?n=10000')
.reply(200)
.get('/node/tags/list?n=10000')
.reply(200, { tags: ['1'] })
Expand Down Expand Up @@ -1280,7 +1328,9 @@ describe('modules/datasource/docker/index', () => {
httpMock
.scope('https://registry.company.com/v2')
.get('/')
.times(4)
.times(3)
.reply(200)
.get('/node/tags/list?n=10000')
.reply(200)
.get('/node/tags/list?n=10000')
.reply(200, { tags: ['1'] })
Expand Down Expand Up @@ -1323,7 +1373,8 @@ describe('modules/datasource/docker/index', () => {
httpMock
.scope('https://registry.company.com/v2')
.get('/')
.times(2)
.reply(200)
.get('/node/tags/list?n=10000')
.reply(200)
.get('/node/tags/list?n=10000')
.reply(200, { tags: ['latest'] })
Expand All @@ -1349,7 +1400,11 @@ describe('modules/datasource/docker/index', () => {
badheaders: ['authorization'],
})
.get('/')
.times(3)
.times(2)
.reply(401, '', {
'www-authenticate': 'Basic realm="My Private Docker Registry Server"',
})
.get('/node/tags/list?n=10000')
.reply(401, '', {
'www-authenticate': 'Basic realm="My Private Docker Registry Server"',
});
Expand Down

0 comments on commit 972b327

Please sign in to comment.