Press n or j to go to the next uncovered block, b, p or k for the previous block.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 | 29x 29x 29x 104x 104x 104x 104x 6x 104x 104x 195x 195x 247x 247x 115x 104x 104x 49x 121x 121x 121x 121x 122x 122x 6x 116x 116x 116x 116x 116x 2x 116x 111x 111x 111x 111x 215x 215x 3x 104x 182x 33x 33x 31x 32x 29x 29x 33x 2x 33x | // from openapi spec - // Assertation 1: // Swagger 2 // For security scheme types other than OAuth2, the security array MUST be empty. // https://github.com/OAI/OpenAPI-Specification/blob/master/versions/2.0.md#securityRequirementObject // OpenAPI 3 // If the security scheme is of type "oauth2" or "openIdConnect", then the value is a list of scope // names required for the execution. For other security scheme types, the array MUST be empty. // https://github.com/OAI/OpenAPI-Specification/blob/master/versions/3.0.0.md#securityRequirementObject // Assertation 2 // Items in `security` must match a `securityDefinition`. const each = require('lodash/each'); const MessageCarrier = require('../../../utils/messageCarrier'); module.exports.validate = function({ jsSpec, isOAS3 }, config) { const messages = new MessageCarrier(); config = config.security; // check all instances of 'security' objects const securityObjects = []; // security objects can exist at either: // 1) the top level of the spec (global definition) if (jsSpec.security) { securityObjects.push({ security: jsSpec.security, path: 'security' }); } // 2) within operations objects const paths = jsSpec.paths; each(paths, (operations, pathName) => { Iif (pathName.slice(0, 2) === 'x-') return; each(operations, (operation, opName) => { Iif (opName.slice(0, 2) === 'x-') return; if (operation.security) { securityObjects.push({ security: operation.security, path: `paths.${pathName}.${opName}.security` }); } }); }); const securityDefinitions = isOAS3 ? jsSpec.components && jsSpec.components.securitySchemes : jsSpec.securityDefinitions; if (securityObjects.length) { securityObjects.forEach(obj => { validateSecurityObject(obj); }); } function validateSecurityObject({ security, path }) { security.forEach(schemeObject => { const schemeNames = Object.keys(schemeObject); schemeNames.forEach(schemeName => { const schemeIsDefined = securityDefinitions && securityDefinitions[schemeName]; // ensure the security scheme is defined if (!schemeIsDefined) { messages.addMessage( `${path}.${schemeName}`, 'security requirements must match a security definition', 'error' ); } else { const schemeType = securityDefinitions[schemeName].type; const isNonEmptyArray = schemeObject[schemeName].length > 0; const schemesWithNonEmptyArrays = isOAS3 ? ['oauth2', 'openIdConnect'] : ['oauth2']; const isSchemeWithNonEmptyArray = schemesWithNonEmptyArrays.includes( schemeType ); if (isNonEmptyArray && !isSchemeWithNonEmptyArray) { messages.addMessage( `${path}.${schemeName}`, `For security scheme types other than ${schemesWithNonEmptyArrays.join( ' or ' )}, the value must be an empty array.`, config.invalid_non_empty_security_array, 'invalid_non_empty_security_array' ); } if (isSchemeWithNonEmptyArray) { // check for resolution of specific scopes const scopes = schemeObject[schemeName]; Eif (Array.isArray(scopes)) { // Check for unknown scopes const securityDefinition = securityDefinitions[schemeName]; scopes.forEach((scope, i) => { const scopeIsDefined = isOAS3 ? checkOAS3Scopes(scope, securityDefinition) : checkSwagger2Scopes(scope, securityDefinition); if (!scopeIsDefined) { messages.addMessage( `${path}.${schemeName}.${i}`, `Definition could not be resolved for security scope: ${scope}`, 'error' ); } }); } } } }); }); } return messages; }; // return true if scope is defined function checkSwagger2Scopes(scope, definition) { return Boolean(definition.scopes && definition.scopes[scope]); } // return true if scope is defined function checkOAS3Scopes(scope, definition) { let scopeIsDefined = false; if (definition.flows) { Object.keys(definition.flows).forEach(flowType => { if ( definition.flows[flowType].scopes && definition.flows[flowType].scopes[scope] ) { scopeIsDefined = true; return; } }); } // scopes for openIdConnet are not definied in the document if (definition.type && definition.type === 'openIdConnect') { scopeIsDefined = true; } return scopeIsDefined; } |