From b4a84065a1e658a7be637c7b381d8828dea80a3a Mon Sep 17 00:00:00 2001
From: Florian Greinacher <florian.greinacher@siemens.com>
Date: Fri, 1 Oct 2021 08:07:33 +0200
Subject: [PATCH] feat(docker): add support for authenticating at ECR with
 session tokens (#11967)

---
 lib/datasource/docker/common.ts     |  2 +
 lib/datasource/docker/index.spec.ts | 58 ++++++++++++++++++++++++-----
 2 files changed, 50 insertions(+), 10 deletions(-)

diff --git a/lib/datasource/docker/common.ts b/lib/datasource/docker/common.ts
index 3b101a6a25..9b9288ad56 100644
--- a/lib/datasource/docker/common.ts
+++ b/lib/datasource/docker/common.ts
@@ -33,8 +33,10 @@ async function getECRAuthToken(
     config.credentials = {
       accessKeyId: opts.username,
       secretAccessKey: opts.password,
+      ...(opts.token && { sessionToken: opts.token }),
     };
   }
+
   const ecr = new ECR(config);
   try {
     const data = await ecr.getAuthorizationToken({});
diff --git a/lib/datasource/docker/index.spec.ts b/lib/datasource/docker/index.spec.ts
index 5db28b3582..e223c2bd5f 100644
--- a/lib/datasource/docker/index.spec.ts
+++ b/lib/datasource/docker/index.spec.ts
@@ -201,11 +201,12 @@ describe('datasource/docker/index', () => {
         .reply(401, '', {
           'www-authenticate': 'Basic realm="My Private Docker Registry Server"',
         })
-        .head('/library/some-dep/manifests/some-tag', undefined, {
-          reqheaders: {
-            authorization: 'Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk',
-          },
-        })
+
+        .head('/library/some-dep/manifests/some-tag')
+        .matchHeader(
+          'authorization',
+          'Basic c29tZS11c2VybmFtZTpzb21lLXBhc3N3b3Jk'
+        )
         .reply(200, '', { 'docker-content-digest': 'some-digest' });
       const res = await getDigest(
         { datasource: 'docker', depName: 'some-dep' },
@@ -237,11 +238,48 @@ describe('datasource/docker/index', () => {
         .reply(401, '', {
           'www-authenticate': 'Basic realm="My Private Docker Registry Server"',
         })
-        .head('/node/manifests/some-tag', undefined, {
-          reqheaders: { authorization: 'Basic abc' },
+        .head('/node/manifests/some-tag')
+        .matchHeader('authorization', 'Basic test_token')
+        .reply(200, '', { 'docker-content-digest': 'some-digest' });
+
+      mockEcrAuthResolve({
+        authorizationData: [{ authorizationToken: 'test_token' }],
+      });
+
+      await getDigest(
+        {
+          datasource: 'docker',
+          depName: '123456789.dkr.ecr.us-east-1.amazonaws.com/node',
+        },
+        'some-tag'
+      );
+
+      expect(AWS.ECR).toHaveBeenCalledWith({
+        credentials: {
+          accessKeyId: 'some-username',
+          secretAccessKey: 'some-password',
+        },
+        region: 'us-east-1',
+      });
+    });
+
+    it('passes session token to ECR client', async () => {
+      httpMock
+        .scope(amazonUrl)
+        .get('/')
+        .reply(401, '', {
+          'www-authenticate': 'Basic realm="My Private Docker Registry Server"',
         })
+        .head('/node/manifests/some-tag')
+        .matchHeader('authorization', 'Basic test_token')
         .reply(200, '', { 'docker-content-digest': 'some-digest' });
 
+      hostRules.find.mockReturnValue({
+        username: 'some-username',
+        password: 'some-password',
+        token: 'some-session-token',
+      });
+
       mockEcrAuthResolve({
         authorizationData: [{ authorizationToken: 'test_token' }],
       });
@@ -258,6 +296,7 @@ describe('datasource/docker/index', () => {
         credentials: {
           accessKeyId: 'some-username',
           secretAccessKey: 'some-password',
+          sessionToken: 'some-session-token',
         },
         region: 'us-east-1',
       });
@@ -270,9 +309,8 @@ describe('datasource/docker/index', () => {
         .reply(401, '', {
           'www-authenticate': 'Basic realm="My Private Docker Registry Server"',
         })
-        .head('/node/manifests/some-tag', undefined, {
-          reqheaders: { authorization: 'Basic abc' },
-        })
+        .head('/node/manifests/some-tag')
+        .matchHeader('authorization', 'Basic test')
         .reply(200, '', { 'docker-content-digest': 'some-digest' });
 
       mockEcrAuthResolve({
-- 
GitLab