Skip to content
This repository has been archived by the owner on Aug 19, 2022. It is now read-only.

Commit

Permalink
variables endpoints for org/ shared policies, fix for tty swagger issue
Browse files Browse the repository at this point in the history
  • Loading branch information
cianfoley-nearform committed Apr 4, 2018
1 parent a917aa0 commit bbdd094
Show file tree
Hide file tree
Showing 15 changed files with 304 additions and 6 deletions.
2 changes: 2 additions & 0 deletions docs/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -47,9 +47,11 @@ A brief overview of the Management API calls are as follows, see the [Swagger Do
|/authorization/policies|GET|Fetch all the defined policies|
|/authorization/policies/search|GET|Search for policies by name|
|/authorization/policies/{id}|GET|Fetch a single policy by ID|
|/authorization/policies/{id}/variables|GET|Fetch a template policy's variables by ID|
|/authorization/shared-policies|GET|Fetch all the defined shared policies|
|/authorization/shared-policies/search|GET|Search for shared policies by name|
|/authorization/shared-policies/{id}|GET|Fetch a single shared policy|
|/authorization/shared-policies/{id}/variables|GET|Fetch a template shared policy's variables by ID|
|/authorization/teams|POST|Create a team|
|/authorization/teams|GET|Fetch all teams from the current user organization|
|/authorization/teams/search|GET|Search for teams from the current user organization|
Expand Down
2 changes: 1 addition & 1 deletion docs/swagger/swagger-json.js

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/swagger/swagger.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions docs/swagger/udaru.json

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
"start": "node packages/udaru-server/start.js",
"test": "lerna run test",
"test:commit-check": "npm run doc:lint && npm run lint && npm run depcheck && npm run test",
"swagger-gen": "node scripts/getSwaggerJson.js | swagger-gen -d docs/swagger && node scripts/injectUdaruSwaggerCss.js"
"swagger-gen": "node scripts/getSwaggerJson.js > docs/swagger/swagger.json && swagger-gen docs/swagger/udaru.json -d docs/swagger && node scripts/injectUdaruSwaggerCss.js"
},
"remarkConfig": {
"plugins": [
Expand Down
1 change: 1 addition & 0 deletions packages/udaru-core/auth.js
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ const Actions = {
DeletePolicy: 'authorization:policies:delete',
ListPolicies: 'authorization:policies:list',
SearchPolicies: 'authorization:policies:search',
ReadPolicyVariables: 'authorization:policies:variables',
AllPolicy: 'authorization:policies:*',

// authorization
Expand Down
5 changes: 5 additions & 0 deletions packages/udaru-core/config.js
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,11 @@ const defaultConfig = {
Effect: 'Allow',
Action: [Action.ReadPolicy],
Resource: [resources.policies({ organizationId: ':organizationId' })]
},
{
Effect: 'Allow',
Action: [Action.ReadPolicyVariables],
Resource: [resources.policies({ organizationId: ':organizationId' })]
}
]
}
Expand Down
3 changes: 2 additions & 1 deletion packages/udaru-core/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,8 @@ function buildUdaruCore (dbPool, config) {
updateShared: hooks.wrap('policy:updateShared', policyOps.updateSharedPolicy),
deleteShared: hooks.wrap('policy:deleteShared', policyOps.deleteSharedPolicy),
readShared: hooks.wrap('policy:readShared', policyOps.readSharedPolicy),
search: hooks.wrap('policy:search', policyOps.search)
search: hooks.wrap('policy:search', policyOps.search),
readPolicyVariables: hooks.wrap('policy:variables', policyOps.readPolicyVariables)
},

teams: {
Expand Down
52 changes: 52 additions & 0 deletions packages/udaru-core/lib/ops/policyOps.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ const mapping = require('../mapping')
const utils = require('./utils')
const uuidV4 = require('uuid/v4')
const validationRules = require('./validation').policies
const _ = require('lodash')

function toArrayWithId (policies) {
if (Array.isArray(policies)) {
Expand Down Expand Up @@ -217,6 +218,56 @@ function buildPolicyOps (db, config) {
return promise
},

/**
* fetch specific policy variables
*
* @param {Object} params { id, organizationId, type } "type" is optional, defaults to organization policies
* @param {Function} cb
*/
readPolicyVariables: function readPolicyVariables ({ id, organizationId, type }, cb) {
let promise = null
if (typeof cb !== 'function') [promise, cb] = asyncify()

Joi.validate({ id, organizationId, type }, validationRules.readPolicyVariables, function (err) {
if (err) return cb(Boom.badRequest(err))

const sqlQuery = SQL`
SELECT *
FROM policies
WHERE id = ${id}
`

if (type === 'shared') {
sqlQuery.append(SQL` AND org_id is NULL`)
} else {
sqlQuery.append(SQL` AND org_id=${organizationId}`)
}

db.query(sqlQuery, function (err, result) {
if (err) return cb(Boom.badImplementation(err))
if (result.rowCount === 0) return cb(Boom.notFound())

let variables = []

_.each(result.rows[0].statements.Statement, function (statement) {
if (statement.Resource) {
_.map(statement.Resource, function (resource) {
// ignore context vars but list all others, should match validation.js
let variableMatches = resource.match(/\${((?!(udaru)|(request)).*)(.+?)}/g)
_.each(variableMatches, function (variable) {
variables.push(variable)
})
})
}
})

return cb(null, variables)
})
})

return promise
},

/**
* Creates a new policy
*
Expand Down Expand Up @@ -736,6 +787,7 @@ function buildPolicyOps (db, config) {
policyOps.updatePolicy.validate = validationRules.updatePolicy
policyOps.deletePolicy.validate = validationRules.deletePolicy
policyOps.search.validate = validationRules.searchPolicy
policyOps.readPolicyVariables.validate = validationRules.readPolicyVariables

policyOps.listSharedPolicies.validate = validationRules.listSharedPolicies
policyOps.readSharedPolicy.validate = validationRules.readSharedPolicy
Expand Down
5 changes: 5 additions & 0 deletions packages/udaru-core/lib/ops/validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,11 @@ const policies = {
id: validationRules.policyId,
organizationId: validationRules.organizationId
},
readPolicyVariables: {
id: validationRules.policyId,
organizationId: validationRules.organizationId,
type: Joi.string().optional().allow('shared', 'organization').description('Flag to denote policy type, defaults to organization')
},
createPolicy: {
id: validationRules.policyId.allow('').optional(),
version: validationRules.version,
Expand Down
81 changes: 79 additions & 2 deletions packages/udaru-core/test/integration/policyOps.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -253,6 +253,42 @@ lab.experiment('PolicyOps', () => {
}]
}
},
policyWithVariablesAndContext: {
name: 'policyWithVariablesAndContext',
id: 'policyWithVariablesAndContext',
organizationId: orgId,
statements: {
Statement: [{
Effect: 'Allow',
Action: ['dummy'],
Resource: ['${varX}', '${varY}', '${udaru.userId}', '${request.currentTime}']
}]
}
},
policyWithJustContextVars: {
name: 'policyWithJustContextVars',
id: 'policyWithJustContextVars',
organizationId: orgId,
statements: {
Statement: [{
Effect: 'Allow',
Action: ['dummy'],
Resource: ['${udaru.userId}', '${request.currentTime}']
}]
}
},
policyWithResource: {
name: 'policyWithResource',
id: 'policyWithResource',
organizationId: orgId,
statements: {
Statement: [{
Effect: 'Allow',
Action: ['dummy'],
Resource: ['xyz']
}]
}
},
policyWithoutVariables: {
name: 'policyWithoutVariables',
organizationId: orgId,
Expand All @@ -267,7 +303,18 @@ lab.experiment('PolicyOps', () => {
},
sharedPolicies: {
sharedPolicy: { name: 'sharedPolicy1' },
unusedPolicy: { name: 'unusedPolicy1' }
unusedPolicy: { name: 'unusedPolicy1' },
sharedPolicyWithVariablesAndContext: {
name: 'sharedPolicyWithVariablesAndContext',
id: 'sharedPolicyWithVariablesAndContext',
statements: {
Statement: [{
Effect: 'Allow',
Action: ['dummy'],
Resource: ['${varA}', '${varB}', '${udaru.userId}', '${request.currentTime}']
}]
}
}
}
}, udaru)

Expand All @@ -283,6 +330,36 @@ lab.experiment('PolicyOps', () => {
})
})

lab.test('lists correct policy variables', (done) => {
policyOps.readPolicyVariables({ id: 'policyWithVariablesAndContext', organizationId: orgId }, (err, results) => {
if (err) return done(err)
expect(results).to.have.length(2)
expect(results).to.contain('${varX}')
expect(results).to.contain('${varY}')

policyOps.readPolicyVariables({ id: 'policyWithJustContextVars', organizationId: orgId }, (err, results) => {
if (err) return done(err)
expect(results).to.have.length(0)

policyOps.readPolicyVariables({ id: 'policyWithResource', organizationId: orgId }, (err, results) => {
if (err) return done(err)
expect(results).to.have.length(0)
done()
})
})
})
})

lab.test('lists correct shared policy variables', (done) => {
policyOps.readPolicyVariables({ id: 'sharedPolicyWithVariablesAndContext', organizationId: orgId, type: 'shared' }, (err, results) => {
if (err) return done(err)
expect(results).to.have.length(2)
expect(results).to.contain('${varA}')
expect(results).to.contain('${varB}')
done()
})
})

lab.test('search policies, no results', (done) => {
policyOps.search({ organizationId: 'WONKA', query: 'bibbidybobbedy' }, (err, results) => {
if (err) return done(err)
Expand Down Expand Up @@ -313,7 +390,7 @@ lab.experiment('PolicyOps', () => {
lab.test('search all policies', (done) => {
policyOps.search({ organizationId: 'WONKA', query: 'a', type: 'all' }, (err, results) => {
if (err) return done(err)
expect(results).to.have.length(13)
expect(results).to.have.length(14)
expect(results[0].name.toLowerCase()).to.contain('a')
expect(results[6].name.toLowerCase()).to.contain('a')
expect(results[12].name.toLowerCase()).to.contain('a')
Expand Down
54 changes: 54 additions & 0 deletions packages/udaru-hapi-plugin/routes/public/policies.js
Original file line number Diff line number Diff line change
Expand Up @@ -75,6 +75,60 @@ exports.register = function (server, options, next) {
}
})

server.route({
method: 'GET',
path: '/authorization/policies/{id}/variables',
handler: function (request, reply) {
const { organizationId } = request.udaru
const { id } = request.params

request.udaruCore.policies.readPolicyVariables({ id, organizationId, type: 'organization' }, reply)
},
config: {
validate: {
params: _.pick(validation.readPolicy, ['id']),
headers
},
description: 'Fetch a template policy\'s variables',
notes: 'The GET /authorization/policies/{id}/variables endpoint returns policy variables based on its ID.\n',
tags: ['api', 'policies'],
plugins: {
auth: {
action: Action.ReadPolicyVariables,
getParams: (request) => ({ policyId: request.params.id })
}
},
response: { schema: swagger.TemplatePolicyVariables }
}
})

server.route({
method: 'GET',
path: '/authorization/shared-policies/{id}/variables',
handler: function (request, reply) {
const { organizationId } = request.udaru
const { id } = request.params

request.udaruCore.policies.readPolicyVariables({ id, organizationId, type: 'shared' }, reply)
},
config: {
validate: {
params: _.pick(validation.readPolicy, ['id']),
headers
},
description: 'Fetch a template shared policy\'s variables',
notes: 'The GET /authorization/policies/{id}/variables endpoint returns shared policy variables based on its ID.\n',
tags: ['api', 'policies'],
plugins: {
auth: {
action: Action.ReadPolicyVariables,
getParams: (request) => ({ policyId: request.params.id })
}
},
response: { schema: swagger.TemplatePolicyVariables }
}
})

server.route({
method: 'GET',
path: '/authorization/shared-policies',
Expand Down
3 changes: 3 additions & 0 deletions packages/udaru-hapi-plugin/swagger.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@ const PolicyRef = Joi.object({
}).label('PolicyRef')
const PolicyRefs = Joi.array().items(PolicyRef).description('Policy Refs').label('PolicyRefs')

const PolicyTemplateVariables = Joi.array().items(Joi.string()).description('Policy Template Variable Placeholders').label('Policy Template Variables')

const UserRef = Joi.object({
id: Joi.string().description('User ID'),
name: Joi.string().description('User name')
Expand Down Expand Up @@ -163,6 +165,7 @@ module.exports = {
Organization,
OrganizationAndUser,
PolicyStatements,
PolicyTemplateVariables,
Access,
Search,
SearchUser,
Expand Down
Loading

0 comments on commit bbdd094

Please sign in to comment.