mirror of
https://github.com/renovatebot/renovate.git
synced 2025-01-12 06:56:24 +00:00
feat(docker): Support for Bearer token to access the Docker registry (#10400)
This commit is contained in:
parent
5c21d44055
commit
d4a22c7f3c
3 changed files with 101 additions and 1 deletions
|
@ -206,6 +206,53 @@ module.exports = {
|
|||
};
|
||||
```
|
||||
|
||||
#### Google Container Registry
|
||||
|
||||
Assume you are running GitLab CI in the Google Cloud, and you are storing your Docker images in the Google Container Registry (GCR).
|
||||
|
||||
Access to the GCR uses Bearer token based authentication.
|
||||
This token can be obtained by running `gcloud auth print-access-token`, which requires the Google Cloud SDK to be installed.
|
||||
|
||||
The token expires after 60 minutes so you cannot store it in a variable for subsequent builds (like you can with `RENOVATE_TOKEN`).
|
||||
|
||||
When running Renovate in this context the Google access token must be retrieved and injected into the `hostRules` configuration just before Renovate is started.
|
||||
|
||||
_This documentation gives **a few hints** on **a possible way** to achieve this end result._
|
||||
|
||||
The basic approach is that you create a custom image and then run Renovate as one of the stages of your project.
|
||||
To make this run independent of any user you should use a [`Project Access Token`](https://docs.gitlab.com/ee/user/project/settings/project_access_tokens.html) (with Scopes: `api`, `read_api` and `write_repository`) for the project and use this as the `RENOVATE_TOKEN` variable for Gitlab CI.
|
||||
See also the [renovate-runner repository on GitLab](https://gitlab.com/renovate-bot/renovate-runner) where `.gitlab-ci.yml` configuration examples can be found.
|
||||
|
||||
To get access to the token a custom Renovate Docker image is needed that includes the Google Cloud SDK.
|
||||
The Dockerfile to create such an image can look like this:
|
||||
|
||||
```Dockerfile
|
||||
FROM renovate/renovate:25.40.1
|
||||
# Include the "Docker tip" which you can find here https://cloud.google.com/sdk/docs/install
|
||||
# under "Installation" for "Debian/Ubuntu"
|
||||
RUN ...
|
||||
```
|
||||
|
||||
For Renovate to access the Google Container Registry (GCR) it needs the current Google Access Token.
|
||||
The configuration fragment to do that looks something like this:
|
||||
|
||||
```js
|
||||
hostRules: [
|
||||
{
|
||||
matchHost: 'eu.gcr.io',
|
||||
token: 'MyReallySecretTokenThatExpiresAfter60Minutes',
|
||||
},
|
||||
];
|
||||
```
|
||||
|
||||
One way to provide the short-lived Google Access Token to Renovate is by generating these settings into a `config.js` file from within the `.gitlab-ci.yml` right before starting Renovate:
|
||||
|
||||
```yaml
|
||||
script:
|
||||
- 'echo "module.exports = { hostRules: [ { matchHost: ''eu.gcr.io'', token: ''"$(gcloud auth print-access-token)"'' } ] };" > config.js'
|
||||
- renovate $RENOVATE_EXTRA_FLAGS
|
||||
```
|
||||
|
||||
#### ChartMuseum
|
||||
|
||||
Maybe you're running your own ChartMuseum server to host your private Helm Charts.
|
||||
|
|
|
@ -1,3 +1,4 @@
|
|||
import * as httpMock from '../../../test/http-mock';
|
||||
import { getName, mocked } from '../../../test/util';
|
||||
import * as _hostRules from '../../util/host-rules';
|
||||
import * as dockerCommon from './common';
|
||||
|
@ -70,4 +71,48 @@ describe(getName(), () => {
|
|||
`);
|
||||
});
|
||||
});
|
||||
describe('getAuthHeaders', () => {
|
||||
beforeEach(() => {
|
||||
httpMock
|
||||
.scope('https://my.local.registry')
|
||||
.get('/v2/')
|
||||
.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',
|
||||
});
|
||||
|
||||
const headers = await dockerCommon.getAuthHeaders(
|
||||
'https://my.local.registry',
|
||||
'https://my.local.registry/prefix'
|
||||
);
|
||||
|
||||
expect(headers).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"authorization": "some-authType some-token",
|
||||
}
|
||||
`);
|
||||
});
|
||||
|
||||
it('returns "Bearer token" if only token provided', async () => {
|
||||
hostRules.find.mockReturnValue({
|
||||
token: 'some-token',
|
||||
});
|
||||
|
||||
const headers = await dockerCommon.getAuthHeaders(
|
||||
'https://my.local.registry',
|
||||
'https://my.local.registry/prefix'
|
||||
);
|
||||
|
||||
expect(headers).toMatchInlineSnapshot(`
|
||||
Object {
|
||||
"authorization": "Bearer some-token",
|
||||
}
|
||||
`);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
|
|
@ -81,12 +81,20 @@ export async function getAuthHeaders(
|
|||
'base64'
|
||||
);
|
||||
opts.headers = { authorization: `Basic ${auth}` };
|
||||
} else if (opts.token) {
|
||||
const authType = opts.authType ?? 'Bearer';
|
||||
logger.trace(
|
||||
`Using ${authType} token for Docker registry ${registryHost}`
|
||||
);
|
||||
opts.headers = { authorization: `${authType} ${opts.token}` };
|
||||
return opts.headers;
|
||||
}
|
||||
delete opts.username;
|
||||
delete opts.password;
|
||||
delete opts.token;
|
||||
|
||||
if (authenticateHeader.scheme.toUpperCase() === 'BASIC') {
|
||||
logger.debug(`Using Basic auth for docker registry ${dockerRepository}`);
|
||||
logger.trace(`Using Basic auth for docker registry ${registryHost}`);
|
||||
await http.get(apiCheckUrl, opts);
|
||||
return opts.headers;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue