Skip to content

Commit

Permalink
Merge pull request #12 from crimson-gao/credentials-provider
Browse files Browse the repository at this point in the history
feat: support credentialsProvider
  • Loading branch information
crimson-gao authored Nov 28, 2024
2 parents 6cc2220 + 2c4b897 commit 60075d5
Show file tree
Hide file tree
Showing 5 changed files with 4,339 additions and 10 deletions.
60 changes: 60 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,63 @@
```
ACCESS_KEY_ID=<key> ACCESS_KEY_SECRET=<secret> TEST_PROJECT=<project you have created> TEST_STORE=<test store without index> TEST_STORE2=<test store with index> make test
```

## Init Client

### Use permanent accessKey

use region

```javaScript
const client = new Client({
accessKeyId: "your_access_key_id",
accessKeySecret: "your_access_key_secret",
region: 'cn-hangzhou'
});
```

or use endpoint

```javaScript
const client = new Client({
accessKeyId: "your_access_key_id",
accessKeySecret: "your_access_key_secret",
endpoint: 'cn-hangzhou.log.aliyuncs.com'
});
```

### Use Credentials Provider

The CredentialsProvider offers a more convenient and secure way to obtain credentials from external sources. You can retrieve these credentials from your server or other Alibaba Cloud services, and rotate them on a regular basis.

```javaScript
const yourCredentialsProvider = new YourCredentialsProvider();
const client = new Client({
credentialsProvider: yourCredentialsProvider,
region: 'cn-hangzhou'
});
```

The credentialsProvider implemented by yourself must be an object that has a property named `getCredentials`, and `getCredentials` is a callable function/method that returns a credentials object.

The returned credentials object from `getCredentials` must not be null or undefined, and has properties named `accessKeyId`, `accessKeySecret` and `securityToken`.

Here is a simple example of a credentialsProvider:

```javaScript
class YourCredentialsProvider {
constructor() {
this.credentials = {
accessKeyId: "your_access_key_id",
accessKeySecret: "your_access_key_secret",
securityToken: "your_security_token"
};
}
// The method getCredentials is called by client to get credentials for signing and authentication.
// Caching and refreshing logic is required in your implementation for performance.
getCredentials() {
return this.credentials;
}
}
```

39 changes: 33 additions & 6 deletions lib/client.js
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,14 @@ class Client {
this.accessKeyId = config.accessKeyId;
this.accessKeySecret = config.accessKeySecret;
this.securityToken = config.securityToken;
this.credentialsProvider = config.credentialsProvider;

if (this.credentialsProvider) {
if (typeof this.credentialsProvider.getCredentials !== 'function') {
throw new Error('config.credentialsProvider must be an object with getCredentials function');
}
}
this._validateCredentials(this._getCredentials());

// endpoint
if (config.endpoint) {
Expand All @@ -82,6 +90,24 @@ class Client {
}
}

_validateCredentials (credentials) {
if (!credentials || !credentials.accessKeyId || !credentials.accessKeySecret) {
throw new Error('Missing credentials or missing accessKeyId/accessKeySecret in credentials.');
}
return credentials;
}

_getCredentials () {
if (!this.credentialsProvider) {
return {
accessKeyId: this.accessKeyId,
accessKeySecret: this.accessKeySecret,
securityToken: this.securityToken
};
}
return this._validateCredentials(this.credentialsProvider.getCredentials());
}

async _request(verb, projectName, path, queries, body, headers, options) {
var prefix = projectName ? `${projectName}.` : '';
var suffix = queries ? `?${querystring.stringify(queries)}` : '';
Expand All @@ -94,9 +120,10 @@ class Client {
'x-log-signaturemethod': 'hmac-sha1'
}, headers);

const credentials = this._getCredentials();
// support STS stoken
if (this.securityToken) {
mergedHeaders['x-acs-security-token'] = this.securityToken;
if (credentials.securityToken) {
mergedHeaders['x-acs-security-token'] = credentials.securityToken;
}

if (body) {
Expand All @@ -106,7 +133,7 @@ class Client {
}

// verb, path, queries, headers
const sign = this._sign(verb, path, queries, mergedHeaders);
const sign = this._sign(verb, path, queries, mergedHeaders, credentials);
mergedHeaders['authorization'] = sign;

const response = await httpx.request(url, Object.assign({
Expand Down Expand Up @@ -141,7 +168,7 @@ class Client {
return responseBody;
}

_sign(verb, path, queries, headers) {
_sign(verb, path, queries, headers, credentials) {
const contentMD5 = headers['content-md5'] || '';
const contentType = headers['content-type'] || '';
const date = headers['date'];
Expand All @@ -150,9 +177,9 @@ class Client {
const signString = `${verb}\n${contentMD5}\n${contentType}\n` +
`${date}\n${canonicalizedHeaders}${canonicalizedResource}`;
debug('signString: %s', signString);
const signature = kitx.sha1(signString, this.accessKeySecret, 'base64');
const signature = kitx.sha1(signString, credentials.accessKeySecret, 'base64');

return `LOG ${this.accessKeyId}:${signature}`;
return `LOG ${credentials.accessKeyId}:${signature}`;
}

getProject(projectName, options) {
Expand Down
Loading

0 comments on commit 60075d5

Please sign in to comment.