Skip to content
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

minor merge of final changes #186

Merged
merged 5 commits into from
Jun 10, 2024
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: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added ytt implementation to template yaml files (credits mdaugs)
- Vault credentials, pass a vault password to ansible playbook.
- OIDC authentication (credits mdaugs)
- Ansibleforms will now wait for mysql to be ready before initializing

### Changed

Expand All @@ -27,6 +28,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- radio button errors
- some issue with the designer when a field without name was added
- multistep was always successfull (tx to mdaugs)
- using cookie session instead express session

## [5.0.1] - 2024-04-10

Expand Down
14 changes: 7 additions & 7 deletions client/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@
"dependencies": {
"@creativebulma/bulma-tooltip": "*",
"@femessage/log-viewer": "*",
"@fortawesome/fontawesome-svg-core": "~6.4.2",
"@fortawesome/free-brands-svg-icons": "~6.4.2",
"@fortawesome/free-regular-svg-icons": "~6.4.2",
"@fortawesome/free-solid-svg-icons": "~6.4.2",
"@fortawesome/fontawesome-svg-core": "~6.5.2",
"@fortawesome/free-brands-svg-icons": "~6.5.2",
"@fortawesome/free-regular-svg-icons": "~6.5.2",
"@fortawesome/free-solid-svg-icons": "~6.5.2",
"@fortawesome/vue-fontawesome": "2.0.10",
"axios": "~1.6.8",
"axios": "~1.7.2",
"brace": "~0.11.1",
"bulma": "0.9.4",
"bulma-calendar": "6.1.19",
Expand All @@ -28,7 +28,7 @@
"bulma-quickview": "*",
"bulmaswatch": "0.8.1",
"copy-to-clipboard": "~3.3.3",
"core-js": "~3.36.1",
"core-js": "~3.37.1",
"es6-promise": "~4.2.8",
"highlight.js": "9.11.0",
"jsonwebtoken": "^9.0.2",
Expand All @@ -54,7 +54,7 @@
"babel-eslint": "~10.1.0",
"eslint": "~6.8.0",
"eslint-plugin-vue": "~6.2.2",
"nodemon": "~3.0.2",
"nodemon": "~3.1.3",
"sass": "~1.49.11",
"sass-loader": "10.1.1",
"vue-template-compiler": "~2.6.11"
Expand Down
30 changes: 15 additions & 15 deletions server/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -20,52 +20,52 @@
"@outlinewiki/passport-azure-ad-oauth2": "~0.1.0",
"ajv": "~6.12.6",
"ajv-error-parser": "~1.0.7",
"axios": "~1.6.8",
"axios": "~1.7.2",
"bcrypt": "~5.1.0",
"bluebird": "~3.7.2",
"cert-info": "~1.5.1",
"cheerio": "~1.0.0-rc.12",
"connect-history-api-fallback": "~2.0.0",
"core-js": "~3.36.1",
"core-js": "~3.37.1",
"cors": "~2.8.5",
"cron-parser": "~4.9.0",
"dayjs": "1.11.10",
"dayjs": "1.11.11",
"express": "~4.19.2",
"express-session": "~1.18.0",
"cookie-session": "~2.1.0",
"fs-extra": "~11.2.0",
"ip": "2.0.1",
"json-bigint": "~1.0.0",
"ldapjs": "~3.0.7",
"lodash": "~4.17.21",
"modern-passport-http": "~0.3.0",
"moment": "~2.30.1",
"mongodb": "~6.5.0",
"mongodb": "~6.7.0",
"mssql": "~10.0.2",
"multer": "~1.4.5-lts.1",
"mysql2": "~3.9.4",
"mysql2": "~3.10.0",
"node-cache": "~5.1.2",
"node-jq": "~4.3.0",
"node-jq": "~4.4.0",
"nodemailer": "~6.9.8",
"openid-client": "^5.6.5",
"passport": "~0.7.0",
"passport-jwt": "~4.0.1",
"pg": "~8.11.3",
"pg": "~8.12.0",
"read-last-lines": "~1.8.0",
"swagger-ui-express": "~5.0.0",
"swagger-ui-express": "~5.0.1",
"thenby": "~1.3.4",
"winston": "~3.13.0",
"winston-daily-rotate-file": "~5.0.0",
"winston-syslog": "~2.7.0",
"yaml": "~2.3.4"
"yaml": "~2.4.5"
},
"devDependencies": {
"@babel/cli": "~7.23.4",
"@babel/core": "7.23.7",
"@babel/eslint-parser": "7.23.3",
"@babel/node": "~7.22.19",
"@babel/cli": "~7.24.7",
"@babel/core": "7.24.7",
"@babel/eslint-parser": "7.24.7",
"@babel/node": "~7.24.7",
"dotenv": "~16.4.1",
"eslint": "~8.56.0",
"nodemon": "~3.0.3",
"nodemon": "~3.1.3",
"npm-run-all": "*",
"rifraf": "~2.0.3"
},
Expand Down
244 changes: 126 additions & 118 deletions server/src/configure.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,8 @@ if (process.env.NODE_ENV !== 'production' || process.env.FORCE_DOTENV==1 || proc
}
// express is the base http server for nodejs
const express = require('express');
const session = require('express-session');
const session = require('cookie-session');

// cors is a middleware to allow cross origin resource sharing
// some routes/apis we will allow coming from other ip's/sources
// for some internal apis we will not allow cors, all requests can only come
Expand All @@ -29,121 +30,128 @@ const appConfig = require('../config/app.config')
module.exports = app => {

// first time run init
require('./init/')

// passport
app.use(session({
secret: 'AnsibleForms',
resave: false,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());

// we use 3 authentications/authorization strategies
// - basic : with username and password to get jwt tokens
// - azure-ad-oauth2 : microsoft login
// - jwt : to use the jwt tokens
// passport (the auth lib used) is smart, if basic authentication headers are detected
// then the basic authentication strategy kicks and the basic login procedure starts
require('./auth/auth_basic');
require('./auth/auth_jwt');
const auth_azuread = require('./auth/auth_azuread');
auth_azuread.initialize()

const auth_oidc = require('./auth/auth_oidc');
auth_oidc.initialize()

app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));

// import api routes
const awxRoutes = require('./routes/awx.routes')
const jobRoutes = require('./routes/job.routes')
const queryRoutes = require('./routes/query.routes')
const expressionRoutes = require('./routes/expression.routes')
const userRoutes = require('./routes/user.routes')
const groupRoutes = require('./routes/group.routes')
const ldapRoutes = require('./routes/ldap.routes')
const azureadRoutes = require('./routes/azuread.routes')
const oidcRoutes = require('./routes/oidc.routes')
const settingsRoutes = require('./routes/settings.routes')
const credentialRoutes = require('./routes/credential.routes')
const loginRoutes = require('./routes/login.routes')
const schemaRoutes = require('./routes/schema.routes')
const tokenRoutes = require('./routes/token.routes')
const configRoutes = require('./routes/config.routes')
const versionRoutes = require('./routes/version.routes')
const lockRoutes = require('./routes/lock.routes')
const profileRoutes = require('./routes/profile.routes')
const sshRoutes = require('./routes/ssh.routes')
const logRoutes = require('./routes/log.routes')
const knownhostsRoutes = require('./routes/knownhosts.routes')
const helpRoutes = require('./routes/help.routes')
const installRoutes = require('./routes/install.routes')
const repositoryRoutes = require('./routes/repository.routes')

// mysql2 has a bug that can throw an uncaught exception if the mysql server crashes (not enough mem for example)
// also git commands can chain child processes and cause issues
process.on('uncaughtException', function(err) {
// handle the error safely
console.error("An uncaught exception happened, ignore... ",err)
})

// using json web tokens as middleware
// the jwtauthentication strategy from passport (/auth/auth.js)
// is used as a middleware. Every route will check the token for validity
const authobj = passport.authenticate('jwt', { session: false })

// api routes for browser only (no cors)
const swaggerOptions = {
customSiteTitle: "Ansibleforms Swagger UI",
customfavIcon: `${appConfig.baseUrl}favicon.svg`,
customCssUrl: `${appConfig.baseUrl}assets/css/swagger.css`,
docExpansion:"none"
}
// change basePath dynamically
swaggerDocument.basePath = `${appConfig.baseUrl}api/v1`
app.use(`${appConfig.baseUrl}api-docs`, swaggerUi.serve, swaggerUi.setup(swaggerDocument,swaggerOptions));
app.use(`${appConfig.baseUrl}api/v1/schema`, schemaRoutes)

// api routes for querying
app.use(`${appConfig.baseUrl}api/v1/query`,cors(), authobj, queryRoutes)
app.use(`${appConfig.baseUrl}api/v1/expression`,cors(), authobj, expressionRoutes)

// api route for version
app.use(`${appConfig.baseUrl}api/v1/version`,cors(), versionRoutes)
app.use(`${appConfig.baseUrl}api/v1/install`,cors(), installRoutes)

app.use(`${appConfig.baseUrl}api/v1/lock`,cors(),authobj, lockRoutes)
app.use(`${appConfig.baseUrl}api/v1/help`,cors(),authobj, helpRoutes)

// api route for profile
app.use(`${appConfig.baseUrl}api/v1/profile`,cors(), authobj, profileRoutes)

// api routes for authorization
app.use(`${appConfig.baseUrl}api/v1/auth`,cors(), loginRoutes)
app.use(`${appConfig.baseUrl}api/v1/token`,cors(), tokenRoutes)

// api routes for automation actions

// app.use(`${appConfig.baseUrl}api/v1/multistep`,cors(), authobj, multistepRoutes)

// api routes for admin management
app.use(`${appConfig.baseUrl}api/v1/job`,cors(), authobj, jobRoutes)
app.use(`${appConfig.baseUrl}api/v1/user`,cors(), authobj, checkAdminMiddleware, userRoutes)
app.use(`${appConfig.baseUrl}api/v1/group`,cors(), authobj, checkAdminMiddleware, groupRoutes)
app.use(`${appConfig.baseUrl}api/v1/ldap`,cors(), authobj, checkAdminMiddleware, ldapRoutes)
app.use(`${appConfig.baseUrl}api/v1/azuread`,cors(), authobj, checkAdminMiddleware, azureadRoutes)
app.use(`${appConfig.baseUrl}api/v1/oidc`,cors(), authobj, checkAdminMiddleware, oidcRoutes)
app.use(`${appConfig.baseUrl}api/v1/settings`,cors(), authobj, checkAdminMiddleware, settingsRoutes)
app.use(`${appConfig.baseUrl}api/v1/credential`,cors(), authobj, checkAdminMiddleware, credentialRoutes)
app.use(`${appConfig.baseUrl}api/v1/sshkey`,cors(), authobj, checkAdminMiddleware, sshRoutes)
app.use(`${appConfig.baseUrl}api/v1/awx`,cors(), authobj, checkAdminMiddleware, awxRoutes)
app.use(`${appConfig.baseUrl}api/v1/log`,cors(), authobj, checkAdminMiddleware, logRoutes)
app.use(`${appConfig.baseUrl}api/v1/repository`,cors(), authobj, checkAdminMiddleware, repositoryRoutes)
app.use(`${appConfig.baseUrl}api/v1/knownhosts`,cors(), authobj, checkAdminMiddleware, knownhostsRoutes)

// routes for form config (extra middleware in the routes itself)
app.use(`${appConfig.baseUrl}api/v1/config`,cors(), authobj, configRoutes)
// from now on, it's async => we wait for mysql to be ready
const init = require('./init/')
init().then(()=>{

// passport
app.use(session({
secret: 'AnsibleForms',
resave: false,
saveUninitialized: true
}));
app.use(passport.initialize());
app.use(passport.session());

// we use 4 authentications/authorization strategies
// - basic : with username and password to get jwt tokens
// - azure-ad-oauth2 : microsoft login
// - oidc : open id connect
// - jwt : to use the jwt tokens
// passport (the auth lib used) is smart, if basic authentication headers are detected
// then the basic authentication strategy kicks and the basic login procedure starts
require('./auth/auth_basic');
require('./auth/auth_jwt');
const auth_azuread = require('./auth/auth_azuread');
auth_azuread.initialize()

const auth_oidc = require('./auth/auth_oidc');
auth_oidc.initialize()

app.use(bodyParser.json({limit: '50mb'}));
app.use(bodyParser.urlencoded({limit: '50mb', extended: true}));

// import api routes
const awxRoutes = require('./routes/awx.routes')
const jobRoutes = require('./routes/job.routes')
const queryRoutes = require('./routes/query.routes')
const expressionRoutes = require('./routes/expression.routes')
const userRoutes = require('./routes/user.routes')
const groupRoutes = require('./routes/group.routes')
const ldapRoutes = require('./routes/ldap.routes')
const azureadRoutes = require('./routes/azuread.routes')
const oidcRoutes = require('./routes/oidc.routes')
const settingsRoutes = require('./routes/settings.routes')
const credentialRoutes = require('./routes/credential.routes')
const loginRoutes = require('./routes/login.routes')
const schemaRoutes = require('./routes/schema.routes')
const tokenRoutes = require('./routes/token.routes')
const configRoutes = require('./routes/config.routes')
const versionRoutes = require('./routes/version.routes')
const lockRoutes = require('./routes/lock.routes')
const profileRoutes = require('./routes/profile.routes')
const sshRoutes = require('./routes/ssh.routes')
const logRoutes = require('./routes/log.routes')
const knownhostsRoutes = require('./routes/knownhosts.routes')
const helpRoutes = require('./routes/help.routes')
const installRoutes = require('./routes/install.routes')
const repositoryRoutes = require('./routes/repository.routes')

// mysql2 has a bug that can throw an uncaught exception if the mysql server crashes (not enough mem for example)
// also git commands can chain child processes and cause issues
process.on('uncaughtException', function(err) {
// handle the error safely
console.error("An uncaught exception happened, ignore... ",err)
})

// using json web tokens as middleware
// the jwtauthentication strategy from passport (/auth/auth.js)
// is used as a middleware. Every route will check the token for validity
const authobj = passport.authenticate('jwt', { session: false })

// api routes for browser only (no cors)
const swaggerOptions = {
customSiteTitle: "Ansibleforms Swagger UI",
customfavIcon: `${appConfig.baseUrl}favicon.svg`,
customCssUrl: `${appConfig.baseUrl}assets/css/swagger.css`,
docExpansion:"none"
}
// change basePath dynamically
swaggerDocument.basePath = `${appConfig.baseUrl}api/v1`
app.use(`${appConfig.baseUrl}api-docs`, swaggerUi.serve, swaggerUi.setup(swaggerDocument,swaggerOptions));
app.use(`${appConfig.baseUrl}api/v1/schema`, schemaRoutes)

// api routes for querying
app.use(`${appConfig.baseUrl}api/v1/query`,cors(), authobj, queryRoutes)
app.use(`${appConfig.baseUrl}api/v1/expression`,cors(), authobj, expressionRoutes)

// api route for version
app.use(`${appConfig.baseUrl}api/v1/version`,cors(), versionRoutes)
app.use(`${appConfig.baseUrl}api/v1/install`,cors(), installRoutes)

app.use(`${appConfig.baseUrl}api/v1/lock`,cors(),authobj, lockRoutes)
app.use(`${appConfig.baseUrl}api/v1/help`,cors(),authobj, helpRoutes)

// api route for profile
app.use(`${appConfig.baseUrl}api/v1/profile`,cors(), authobj, profileRoutes)

// api routes for authorization
app.use(`${appConfig.baseUrl}api/v1/auth`,cors(), loginRoutes)
app.use(`${appConfig.baseUrl}api/v1/token`,cors(), tokenRoutes)

// api routes for automation actions

// app.use(`${appConfig.baseUrl}api/v1/multistep`,cors(), authobj, multistepRoutes)

// api routes for admin management
app.use(`${appConfig.baseUrl}api/v1/job`,cors(), authobj, jobRoutes)
app.use(`${appConfig.baseUrl}api/v1/user`,cors(), authobj, checkAdminMiddleware, userRoutes)
app.use(`${appConfig.baseUrl}api/v1/group`,cors(), authobj, checkAdminMiddleware, groupRoutes)
app.use(`${appConfig.baseUrl}api/v1/ldap`,cors(), authobj, checkAdminMiddleware, ldapRoutes)
app.use(`${appConfig.baseUrl}api/v1/azuread`,cors(), authobj, checkAdminMiddleware, azureadRoutes)
app.use(`${appConfig.baseUrl}api/v1/oidc`,cors(), authobj, checkAdminMiddleware, oidcRoutes)
app.use(`${appConfig.baseUrl}api/v1/settings`,cors(), authobj, checkAdminMiddleware, settingsRoutes)
app.use(`${appConfig.baseUrl}api/v1/credential`,cors(), authobj, checkAdminMiddleware, credentialRoutes)
app.use(`${appConfig.baseUrl}api/v1/sshkey`,cors(), authobj, checkAdminMiddleware, sshRoutes)
app.use(`${appConfig.baseUrl}api/v1/awx`,cors(), authobj, checkAdminMiddleware, awxRoutes)
app.use(`${appConfig.baseUrl}api/v1/log`,cors(), authobj, checkAdminMiddleware, logRoutes)
app.use(`${appConfig.baseUrl}api/v1/repository`,cors(), authobj, checkAdminMiddleware, repositoryRoutes)
app.use(`${appConfig.baseUrl}api/v1/knownhosts`,cors(), authobj, checkAdminMiddleware, knownhostsRoutes)

// routes for form config (extra middleware in the routes itself)
app.use(`${appConfig.baseUrl}api/v1/config`,cors(), authobj, configRoutes)

})


}
Loading