Skip to content

deprecate static Admin token generation. #45

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 22, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .circleci/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,7 @@ workflows:
- "build-dev":
filters:
branches:
only: dev
only: [dev, 'feature/m2mtoken']
- "build-prod":
filters:
branches:
Expand Down
17 changes: 0 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,6 @@ The following parameters can be set in config files or in env variables:
- `TC_API_V3_BASE_URL`: the TopCoder API V3 base URL
- `TC_API_V4_BASE_URL`: the TopCoder API V4 base URL
- `MESSAGE_API_BASE_URL`: the TopCoder message service API base URL
- `TC_ADMIN_TOKEN`: the admin token to access TopCoder API - same for V3 and V4
- **Topcder specific**<br>
Also it has probably temporary variables of TopCoder role ids for 'Connect Manager', 'Connect Copilot' and 'administrator':
- `CONNECT_MANAGER_ROLE_ID`: 8,
Expand Down Expand Up @@ -94,29 +93,13 @@ so we can run `node test/token 305384` to generate a token to manage notificatio
The generated token is already configured in the Postman notification server API environment TOKEN variable.
You may reuse it during review.


## TC API Admin Token

An admin token is needed to access TC API. This is already configured Postman notification
server API environment TC_ADMIN_TOKEN variable.
In case it expires, you may get a new token in this way:

- use Chrome to browse connect.topcoder-dev.com
- open developer tools, click the Network tab
- log in with suser1 / Topcoder123, or mess / appirio123
- once logged in, open some project, for example https://connect.topcoder-dev.com/projects/1936 and in the network inspector
look for the call to the project api and get the token from the auth header, see
http://pokit.org/get/img/68cdd34f3d205d6d9bd8bddb07bdc216.jpg


## Local deployment
- for local development environment you can set variables as following:
- `AUTH_SECRET`,`VALID_ISSUERS` can get from [tc-project-service config](https://github.com/topcoder-platform/tc-project-service/blob/dev/config/default.json)
- `PORT=4000` because **connect-app** call this port by default
- `KAFKA_TOPIC_IGNORE_PREFIX=joan-26673.` (with point at the end)
- `TC_API_V4_BASE_URL=https://api.topcoder-dev.com/v4`
- `TC_API_V3_BASE_URL=https://api.topcoder-dev.com/v3`
- `TC_ADMIN_TOKEN=eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9.eyJyb2xlcyI6WyJUb3Bjb2RlciBVc2VyIiwiYWRtaW5pc3RyYXRvciJdLCJpc3MiOiJodHRwczovL2FwaS50b3Bjb2Rlci1kZXYuY29tIiwiaGFuZGxlIjoic3VzZXIxIiwiZXhwIjoxNTEzNDAxMjU4LCJ1c2VySWQiOiI0MDE1MzkzOCIsImlhdCI6MTUwOTYzNzYzOSwiZW1haWwiOiJtdHdvbWV5QGJlYWtzdGFyLmNvbSIsImp0aSI6IjIzZTE2YjA2LWM1NGItNDNkNS1iY2E2LTg0ZGJiN2JiNDA0NyJ9.REds35fdBvY7CMDGGFyT_tOD7DxGimFfVzIyEy9YA0Y` or follow section **TC API Admin Token** to obtain a new one if expired
- `KAFKA_URL`, `KAFKA_CLIENT_CERT` and `KAFKA_CLIENT_CERT_KEY` get from [tc-bus-api readme](https://github.com/topcoder-platform/tc-bus-api/tree/dev)
- if you are willing to use notifications API which is hosted by the notifications server locally, you will need to use some patched `tc-core-library-js` module, which skips verification of user token. Because we don't know Topcoder `AUTH_SECRET` locally. So you can install this fork:
```
Expand Down
1 change: 0 additions & 1 deletion config/default.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,6 @@ module.exports = {
VALID_ISSUERS: process.env.validIssuers ? process.env.validIssuers.replace(/\\"/g, '') : null,
// keep it here for dev purposes, it's only needed by modified version of tc-core-library-js
// which skips token validation when locally deployed
JWKS_URI: process.env.jwksUri,

KAFKA_URL: process.env.KAFKA_URL,
KAFKA_TOPIC_IGNORE_PREFIX: process.env.KAFKA_TOPIC_IGNORE_PREFIX,
Expand Down
1 change: 0 additions & 1 deletion connect/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,6 @@ module.exports = {
TC_API_V3_BASE_URL: process.env.TC_API_V3_BASE_URL || 'https://api.topcoder-dev.com/v3',
TC_API_V4_BASE_URL: process.env.TC_API_V4_BASE_URL || 'https://api.topcoder-dev.com/v4',
MESSAGE_API_BASE_URL: process.env.MESSAGE_API_BASE_URL || 'https://api.topcoder-dev.com/v5',
TC_ADMIN_TOKEN: process.env.TC_ADMIN_TOKEN,

// Probably temporary variables for TopCoder role ids for 'Connect Manager', 'Connect Copilot' and 'administrator'
// These are values for development backend. For production backend they may be different.
Expand Down
143 changes: 80 additions & 63 deletions connect/service.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,52 +14,65 @@ const { logger } = require('../index');
*
* @return {Promise} promise resolved to project details
*/
const getProject = (projectId) => request
.get(`${config.TC_API_V4_BASE_URL}/projects/${projectId}`)
.set('accept', 'application/json')
.set('authorization', `Bearer ${config.TC_ADMIN_TOKEN}`)
.then((res) => {
if (!_.get(res, 'body.result.success')) {
throw new Error(`Failed to get project details of project id: ${projectId}`);
}

const project = _.get(res, 'body.result.content');

return project;
}).catch((err) => {
const errorDetails = _.get(err, 'response.body.result.content.message');
throw new Error(
`Failed to get project details of project id: ${projectId}.` +
(errorDetails ? ' Server response: ' + errorDetails : '')
);
});

const getProject = (projectId) => {
return M2m.getMachineToken(config.AUTH0_CLIENT_ID, config.AUTH0_CLIENT_SECRET)
.then((token) => {
return request
.get(`${config.TC_API_V4_BASE_URL}/projects/${projectId}`)
.set('accept', 'application/json')
.set('authorization', `Bearer ${token}`)
.then((res) => {
if (!_.get(res, 'body.result.success')) {
throw new Error(`Failed to get project details of project id: ${projectId}`);
}
const project = _.get(res, 'body.result.content');
return project;
}).catch((err) => {
const errorDetails = _.get(err, 'response.body.result.content.message');
throw new Error(
`Failed to get project details of project id: ${projectId}.` +
(errorDetails ? ' Server response: ' + errorDetails : '')
);
});
})
.catch((err) => {
err.message = 'Error generating m2m token: ' + err.message;
throw err;
});
};
/**
* Get role members
*
* @param {String} roleId role id
*
* @return {Promise} promise resolved to role members ids list
*/
const getRoleMembers = (roleId) => request
.get(`${config.TC_API_V3_BASE_URL}/roles/${roleId}?fields=subjects`)
.set('accept', 'application/json')
.set('authorization', `Bearer ${config.TC_ADMIN_TOKEN}`)
.then((res) => {
if (!_.get(res, 'body.result.success')) {
throw new Error(`Failed to get role members of role id: ${roleId}`);
}

const members = _.get(res, 'body.result.content.subjects');

return members;
}).catch((err) => {
const errorDetails = _.get(err, 'response.body.result.content.message');
throw new Error(
`Failed to get role members of role id: ${roleId}.` +
(errorDetails ? ' Server response: ' + errorDetails : '')
);
});
const getRoleMembers = (roleId) => {
return M2m.getMachineToken(config.AUTH0_CLIENT_ID, config.AUTH0_CLIENT_SECRET)
.then((token) => {
return request
.get(`${config.TC_API_V3_BASE_URL}/roles/${roleId}?fields=subjects`)
.set('accept', 'application/json')
.set('authorization', `Bearer ${token}`)
.then((res) => {
if (!_.get(res, 'body.result.success')) {
throw new Error(`Failed to get role membrs of role id: ${roleId}`);
}
const members = _.get(res, 'body.result.content.subjects');
return members;
}).catch((err) => {
const errorDetails = _.get(err, 'response.body.result.content.message');
throw new Error(
`Failed to get role membrs of role id: ${roleId}.` +
(errorDetails ? ' Server response: ' + errorDetails : '')
);
});
})
.catch((err) => {
err.message = 'Error generating m2m token: ' + err.message;
throw err;
});
};

/**
* Get users details by ids
Expand All @@ -76,8 +89,6 @@ const getUsersById = (ids) => {
throw err;
})
.then((token) => {
if (!token && config.TC_ADMIN_TOKEN) token = config.TC_ADMIN_TOKEN;

return request
.get(`${config.TC_API_V3_BASE_URL}/members/_search?fields=userId,email,handle,firstName,lastName&query=${query}`)
.set('accept', 'application/json')
Expand Down Expand Up @@ -115,8 +126,6 @@ const getUsersByHandle = (handles) => {
throw err;
})
.then((token) => {
if (!token && config.TC_ADMIN_TOKEN) token = config.TC_ADMIN_TOKEN;

return request
.get(`${config.TC_API_V3_BASE_URL}/members/_search?fields=userId,handle,firstName,lastName&query=${query}`)
.set('accept', 'application/json')
Expand Down Expand Up @@ -146,26 +155,34 @@ const getUsersByHandle = (handles) => {
*
* @return {Promise} promise resolved to topic details
*/
const getTopic = (topicId) => request
.get(`${config.MESSAGE_API_BASE_URL}/topics/${topicId}/read`)
.set('accept', 'application/json')
.set('authorization', `Bearer ${config.TC_ADMIN_TOKEN}`)
.then((res) => {
if (!_.get(res, 'body.result.success')) {
throw new Error(`Failed to get topic details of topic id: ${topicId}`);
}

return _.get(res, 'body.result.content');
}).catch((err) => {
if (logger) {
logger.error(err, `Error while calling ${config.MESSAGE_API_BASE_URL}/topics/${topicId}/read`);
}
const errorDetails = _.get(err, 'response.body.result.content.message');
throw new Error(
`Failed to get topic details of topic id: ${topicId}.` +
(errorDetails ? ' Server response: ' + errorDetails : '')
);
});
const getTopic = (topicId, logger) => {
return M2m.getMachineToken(config.AUTH0_CLIENT_ID, config.AUTH0_CLIENT_SECRET)
.then((token) => {
return request
.get(`${config.MESSAGE_API_BASE_URL}/topics/${topicId}/read`)
.set('accept', 'application/json')
.set('authorization', `Bearer ${token}`)
.then((res) => {
if (!_.get(res, 'body.result.success')) {
throw new Error(`Failed to get topic details of topic id: ${topicId}`);
}
return _.get(res, 'body.result.content');
}).catch((err) => {
if (logger) {
logger.error(err, `Error while calling ${config.MESSAGE_API_BASE_URL}/topics/${topicId}/read`);
}
const errorDetails = _.get(err, 'response.body.result.content.message');
throw new Error(
`Failed to get topic details of topic id: ${topicId}.` +
(errorDetails ? ' Server response: ' + errorDetails : '')
);
});
})
.catch((err) => {
err.message = 'Error generating m2m token: ' + err.message;
throw err;
});
};

module.exports = {
getProject,
Expand Down
17 changes: 1 addition & 16 deletions deploy.sh
Original file line number Diff line number Diff line change
Expand Up @@ -37,11 +37,8 @@ KAFKA_GROUP_ID=$(eval "echo \$${ENV}_KAFKA_GROUP_ID")
KAFKA_TOPIC_IGNORE_PREFIX=$(eval "echo \$${ENV}_KAFKA_TOPIC_IGNORE_PREFIX")
KAFKA_URL=$(eval "echo \$${ENV}_KAFKA_URL")
AUTHSECRET=$(eval "echo \$${ENV}_AUTHSECRET")
AUTHDOMAIN=$(eval "echo \$${ENV}_AUTHDOMAIN")
VALID_ISSUERS=$(eval "echo \$${ENV}_VALID_ISSUERS")
JWKSURI=$(eval "echo \$${ENV}_JWKSURI")
TC_API_BASE_URL=$(eval "echo \$${ENV}_TC_API_BASE_URL")
TC_ADMIN_TOKEN=$(eval "echo \$${ENV}_TC_ADMIN_TOKEN")
LOG_LEVEL=$(eval "echo \$${ENV}_LOG_LEVEL")
PORT=$(eval "echo \$${ENV}_PORT")

Expand Down Expand Up @@ -155,14 +152,6 @@ make_task_def(){
"name": "authSecret",
"value": "%s"
},
{
"name": "authDomain",
"value": "%s"
},
{
"name": "jwksUri",
"value": "%s"
},
{
"name": "TC_API_BASE_URL",
"value": "%s"
Expand All @@ -183,10 +172,6 @@ make_task_def(){
"name": "MESSAGE_API_BASE_URL",
"value": "%s"
},
{
"name": "TC_ADMIN_TOKEN",
"value": "%s"
},
{
"name": "ENABLE_EMAILS",
"value": "%s"
Expand Down Expand Up @@ -266,7 +251,7 @@ make_task_def(){
}
]'

task_def=$(printf "$task_template" $AWS_ECS_CONTAINER_NAME $AWS_ACCOUNT_ID $AWS_REGION $AWS_REPOSITORY $TAG $ENV "$KAFKA_CLIENT_CERT" "$KAFKA_CLIENT_CERT_KEY" $KAFKA_GROUP_ID "$KAFKA_TOPIC_IGNORE_PREFIX" $KAFKA_URL $DATABASE_URL $AUTHSECRET "$AUTHDOMAIN" "$JWKSURI" $TC_API_BASE_URL $TC_API_V3_BASE_URL $TC_API_V4_BASE_URL $TC_API_V5_BASE_URL $MESSAGE_API_BASE_URL $TC_ADMIN_TOKEN $ENABLE_EMAILS $MENTION_EMAIL $REPLY_EMAIL_PREFIX $REPLY_EMAIL_DOMAIN $ENABLE_DEV_MODE $DEV_MODE_EMAIL $LOG_LEVEL $VALID_ISSUERS $PORT "$API_CONTEXT_PATH" "$AUTH0_URL" "$AUTH0_AUDIENCE" $AUTH0_CLIENT_ID "$AUTH0_CLIENT_SECRET" $TOKEN_CACHE_TIME $AWS_ECS_CLUSTER $AWS_REGION $AWS_ECS_CLUSTER $ENV)
task_def=$(printf "$task_template" $AWS_ECS_CONTAINER_NAME $AWS_ACCOUNT_ID $AWS_REGION $AWS_REPOSITORY $TAG $ENV "$KAFKA_CLIENT_CERT" "$KAFKA_CLIENT_CERT_KEY" $KAFKA_GROUP_ID "$KAFKA_TOPIC_IGNORE_PREFIX" $KAFKA_URL $DATABASE_URL $AUTHSECRET $TC_API_BASE_URL $TC_API_V3_BASE_URL $TC_API_V4_BASE_URL $TC_API_V5_BASE_URL $MESSAGE_API_BASE_URL $ENABLE_EMAILS $MENTION_EMAIL $REPLY_EMAIL_PREFIX $REPLY_EMAIL_DOMAIN $ENABLE_DEV_MODE $DEV_MODE_EMAIL $LOG_LEVEL $VALID_ISSUERS $PORT "$API_CONTEXT_PATH" "$AUTH0_URL" "$AUTH0_AUDIENCE" $AUTH0_CLIENT_ID "$AUTH0_CLIENT_SECRET" $TOKEN_CACHE_TIME $AWS_ECS_CLUSTER $AWS_REGION $AWS_ECS_CLUSTER $ENV)
}

register_definition() {
Expand Down