├── .npmrc ├── src ├── config.php ├── Dockerfile ├── lib │ ├── D2LConstants.php │ ├── D2LHostSpec.php │ ├── UserOpSecurityParameters.php │ ├── D2LAppContextFactory.php │ ├── D2LSigner.php │ ├── ID2LUserContext.php │ ├── D2LAppContext.php │ ├── ID2LAppContext.php │ └── D2LUserContext.php ├── authenticateUser.php ├── js │ ├── bootstrap.min.js │ ├── profiles.js │ ├── main.js │ └── jquery.min.js ├── doRequest.php ├── index.php └── css │ └── bootstrap.min.css ├── .npmignore ├── cdk.json ├── .github ├── dependabot.yml └── workflows │ ├── ci.yml │ └── deployment.yml ├── .gitignore ├── README.md ├── lib ├── setup-stack.ts └── app-stack.ts ├── package.json ├── tsconfig.json ├── bin └── pipeline.ts └── LICENSE /.npmrc: -------------------------------------------------------------------------------- 1 | ignore-scripts=true 2 | -------------------------------------------------------------------------------- /src/config.php: -------------------------------------------------------------------------------- 1 | 'lib', 4 | ); 5 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | *.ts 2 | !*.d.ts 3 | 4 | # CDK asset staging directory 5 | .cdk.staging 6 | cdk.out 7 | -------------------------------------------------------------------------------- /src/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM php:8.0-apache 2 | COPY . /var/www/html/ 3 | EXPOSE 80 4 | CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"] -------------------------------------------------------------------------------- /cdk.json: -------------------------------------------------------------------------------- 1 | { 2 | "app": "npx ts-node bin/pipeline.ts", 3 | "context": { 4 | "@aws-cdk/core:newStyleStackSynthesis": false 5 | } 6 | } 7 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | - package-ecosystem: gitsubmodule 4 | directory: "/" 5 | schedule: 6 | interval: daily 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | lib/*.js 2 | bin/*.js 3 | !jest.config.js 4 | *.d.ts 5 | node_modules 6 | 7 | # CDK asset staging directory 8 | cdk.context.json 9 | .cdk.staging 10 | cdk.out 11 | 12 | # Parcel default cache directory 13 | .parcel-cache 14 | .idea/ 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | API-Test-Tool 2 | ============= 3 | 4 | A tool for testing Valence API calls. 5 | 6 | Use it online 7 | ------------- 8 | 9 | WARNING: This tool must be hosted in an isolated VPN to mitigate a known SSRF vulnerability 10 | 11 | D2L hosts a copy of this tool at [apitesttool.desire2learnvalence.com](https://apitesttool.desire2learnvalence.com/) 12 | -------------------------------------------------------------------------------- /lib/setup-stack.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from 'aws-cdk-lib'; 2 | import { aws_ecr as ecr } from 'aws-cdk-lib'; 3 | 4 | export class SetupStack extends cdk.Stack { 5 | 6 | constructor(scope: cdk.App, id: string, props?: cdk.StackProps) { 7 | super(scope, id, props); 8 | 9 | // ECR repository 10 | const repository = new ecr.Repository(this, "api_test_tool_repository", { 11 | repositoryName: "api_test_tool_repository", 12 | imageScanOnPush: true, 13 | removalPolicy: cdk.RemovalPolicy.RETAIN, 14 | }); 15 | } 16 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "infrastructure", 3 | "version": "0.1.0", 4 | "bin": { 5 | "infrastructure": "bin/infrastructure.js" 6 | }, 7 | "scripts": { 8 | "build": "tsc", 9 | "watch": "tsc -w", 10 | "cdk": "cdk" 11 | }, 12 | "dependencies": { 13 | "aws-cdk": "^2.162.1", 14 | "aws-cdk-lib": "^2.162.1", 15 | "ts-node": "^10.9.2", 16 | "typescript": "~5.3.3" 17 | }, 18 | "devDependencies": { 19 | "constructs": "^10.3.0" 20 | }, 21 | "peerDependencies": { 22 | "constructs": "^10.0.0" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "ES2018", 4 | "module": "commonjs", 5 | "lib": ["es2018"], 6 | "declaration": false, 7 | "sourceMap": false, 8 | "strict": true, 9 | "noImplicitAny": true, 10 | "strictNullChecks": true, 11 | "noImplicitThis": true, 12 | "alwaysStrict": true, 13 | "noUnusedLocals": false, 14 | "noUnusedParameters": false, 15 | "noImplicitReturns": true, 16 | "noFallthroughCasesInSwitch": false, 17 | "inlineSourceMap": true, 18 | "inlineSources": true, 19 | "experimentalDecorators": true, 20 | "strictPropertyInitialization": false, 21 | "typeRoots": ["./node_modules/@types"] 22 | }, 23 | "exclude": ["cdk.out"] 24 | } 25 | -------------------------------------------------------------------------------- /src/lib/D2LConstants.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/lib/D2LHostSpec.php: -------------------------------------------------------------------------------- 1 | m_host = $host; 26 | $this->m_port = $port; 27 | $this->m_scheme = $scheme; 28 | } 29 | 30 | public function Host() { 31 | return $this->m_host; 32 | } 33 | 34 | public function Port() { 35 | return $this->m_port; 36 | } 37 | 38 | public function Scheme() { 39 | return $this->m_scheme; 40 | } 41 | } 42 | ?> -------------------------------------------------------------------------------- /src/authenticateUser.php: -------------------------------------------------------------------------------- 1 | createSecurityContext($appId, $appKey); 29 | $hostSpec = new D2LHostSpec($host, $port, $scheme); 30 | $url = $authContext->createUrlForAuthenticationFromHostSpec($hostSpec, $redirectPage); 31 | 32 | header("Location: $url"); 33 | 34 | ?> 35 | -------------------------------------------------------------------------------- /bin/pipeline.ts: -------------------------------------------------------------------------------- 1 | import * as cdk from 'aws-cdk-lib'; 2 | import { AppStack, AppStackProps } from '../lib/app-stack'; 3 | import { SetupStack } from '../lib/setup-stack'; 4 | 5 | const prdAppStackProps: AppStackProps = { 6 | env: { 7 | account: process.env.CDK_DEFAULT_ACCOUNT, 8 | region: "us-east-1" 9 | }, 10 | hostedZoneDomainName: "desire2learnvalence.com", 11 | certificateDomain: "apitesttool.desire2learnvalence.com", 12 | fargateDomainName: "apitesttool.desire2learnvalence.com", 13 | elbLogTargetEnvironment: "prd", 14 | imageTag: process.env.IMAGE_TAG 15 | } 16 | 17 | const devAppStackProps: AppStackProps = { 18 | env: { 19 | account: "111111111111", 20 | region: "ca-central-1", 21 | }, 22 | hostedZoneDomainName: "lti.dev.brightspace.com", 23 | certificateDomain: "apitesttool.lti.dev.brightspace.com", 24 | fargateDomainName: "apitesttool.lti.dev.brightspace.com", 25 | elbLogTargetEnvironment: "dev", 26 | imageTag: "test1" 27 | } 28 | 29 | const app = new cdk.App(); 30 | 31 | new SetupStack(app, "ApiTestToolSetupStack", prdAppStackProps ); 32 | new AppStack(app, "ApiTestToolAppStack", prdAppStackProps ); 33 | 34 | new SetupStack(app, "ApiTestToolSetupStack-Dev", devAppStackProps ); 35 | new AppStack(app, "ApiTestToolAppStack-Dev", devAppStackProps ); 36 | 37 | app.synth(); 38 | -------------------------------------------------------------------------------- /src/lib/UserOpSecurityParameters.php: -------------------------------------------------------------------------------- 1 | userId = $userId; 32 | $this->userKey = $userKey; 33 | $this->appId = $appId; 34 | $this->appKey = $appKey; 35 | $this->hostName = $hostName; 36 | $this->port = $port; 37 | $this->encryptOperations = $encryptOperations; 38 | } 39 | 40 | } 41 | ?> -------------------------------------------------------------------------------- /src/lib/D2LAppContextFactory.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/lib/D2LSigner.php: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | # This is a basic workflow to help you get started with Actions 2 | 3 | name: ci 4 | # Controls when the action will run. Triggers the workflow on push or pull request 5 | # events not on master 6 | on: 7 | push: 8 | branches: 9 | - '**' 10 | - '!master' 11 | 12 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 13 | jobs: 14 | build: 15 | # The type of runner that the job will run on 16 | runs-on: ubuntu-latest 17 | 18 | steps: 19 | - name: checkout@v2 20 | uses: Brightspace/third-party-actions@actions/checkout 21 | 22 | # see: https://github.com/aws-actions/configure-aws-credentials 23 | - name: Assume role 24 | uses: Brightspace/third-party-actions@aws-actions/configure-aws-credentials 25 | with: 26 | aws-region: us-east-1 27 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 28 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 29 | aws-session-token: ${{ secrets.AWS_SESSION_TOKEN }} 30 | role-duration-seconds: 3600 31 | role-skip-session-tagging: true 32 | 33 | - name: Install packages 34 | run: | 35 | npm install typescript 36 | npm i 37 | 38 | - name: Npm Build 39 | run: npm run build 40 | 41 | - name: Cdk Diff ApiTestToolSetupStack 42 | run: npx cdk diff ApiTestToolSetupStack 43 | 44 | - name: Cdk Diff ApiTestToolAppStack 45 | run: npx cdk diff ApiTestToolAppStack 46 | 47 | - name: Log in to Amazon ECR 48 | id: login-ecr 49 | uses: aws-actions/amazon-ecr-login@v1 50 | 51 | - name: Build, tag, and push image to Amazon ECR 52 | env: 53 | ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} 54 | ECR_REPOSITORY: api_test_tool_repository 55 | IMAGE_TAG: ${{ github.sha }} 56 | run: | 57 | # cd .. 58 | docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ./src 59 | docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG 60 | echo $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG 61 | 62 | - name: Log out of Amazon ECR 63 | if: always() 64 | run: docker logout ${{ steps.login-ecr.outputs.registry }} 65 | -------------------------------------------------------------------------------- /.github/workflows/deployment.yml: -------------------------------------------------------------------------------- 1 | name: Deployment 2 | # Controls when the action will run. Triggers the workflow on push or pull request 3 | # events not on master 4 | on: 5 | push: 6 | branches: 7 | - 'master' 8 | 9 | # A workflow run is made up of one or more jobs that can run sequentially or in parallel 10 | jobs: 11 | build: 12 | # The type of runner that the job will run on 13 | runs-on: ubuntu-latest 14 | 15 | steps: 16 | - name: checkout@v2 17 | uses: Brightspace/third-party-actions@actions/checkout 18 | 19 | # see: https://github.com/aws-actions/configure-aws-credentials 20 | - name: Assume role 21 | uses: Brightspace/third-party-actions@aws-actions/configure-aws-credentials 22 | with: 23 | aws-region: us-east-1 24 | aws-access-key-id: ${{ secrets.AWS_ACCESS_KEY_ID }} 25 | aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY }} 26 | aws-session-token: ${{ secrets.AWS_SESSION_TOKEN }} 27 | role-duration-seconds: 3600 28 | role-skip-session-tagging: true 29 | 30 | - name: Install packages 31 | run: | 32 | npm install typescript 33 | npm i 34 | 35 | - name: Npm Build 36 | run: npm run build 37 | 38 | - name: Cdk Diff ApiTestToolSetupStack 39 | run: npx cdk diff ApiTestToolSetupStack 40 | 41 | - name: Cdk Deploy ApiTestToolSetupStack 42 | run: npx cdk deploy ApiTestToolSetupStack --require-approval never 43 | 44 | # see: https://github.com/aws-actions/amazon-ecr-login 45 | - name: Log in to Amazon ECR 46 | id: login-ecr 47 | uses: aws-actions/amazon-ecr-login@v1 48 | 49 | - name: Build, tag, and push image to Amazon ECR 50 | env: 51 | ECR_REGISTRY: ${{ steps.login-ecr.outputs.registry }} 52 | ECR_REPOSITORY: api_test_tool_repository 53 | IMAGE_TAG: ${{ github.sha }} 54 | run: | 55 | # cd .. 56 | docker build -t $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG ./src 57 | docker push $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG 58 | echo $ECR_REGISTRY/$ECR_REPOSITORY:$IMAGE_TAG 59 | 60 | - name: Log out of Amazon ECR 61 | if: always() 62 | run: docker logout ${{ steps.login-ecr.outputs.registry }} 63 | 64 | - name: Cdk Diff ApiTestToolAppStack 65 | run: npx cdk diff ApiTestToolAppStack 66 | 67 | - name: Cdk Deploy ApiTestToolAppStack 68 | run: npx cdk deploy ApiTestToolAppStack --require-approval never 69 | env: 70 | IMAGE_TAG: ${{ github.sha }} 71 | 72 | 73 | 74 | -------------------------------------------------------------------------------- /src/js/bootstrap.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * Bootstrap v3.0.0 3 | * 4 | * Copyright 2013 Twitter, Inc 5 | * Licensed under the Apache License v2.0 6 | * http://www.apache.org/licenses/LICENSE-2.0 7 | * 8 | * Designed and built with all the love in the world @twitter by @mdo and @fat. 9 | */ 10 | 11 | +function(a){function e(){a(b).remove(),a(c).each(function(b){var c=f(a(this));if(!c.hasClass("open"))return;c.trigger(b=a.Event("hide.bs.dropdown"));if(b.isDefaultPrevented())return;c.removeClass("open").trigger("hidden.bs.dropdown")})}function f(b){var c=b.attr("data-target");c||(c=b.attr("href"),c=c&&/#/.test(c)&&c.replace(/.*(?=#[^\s]*$)/,""));var d=c&&a(c);return d&&d.length?d:b.parent()}"use strict";var b=".dropdown-backdrop",c="[data-toggle=dropdown]",d=function(b){var c=a(b).on("click.bs.dropdown",this.toggle)};d.prototype.toggle=function(b){var c=a(this);if(c.is(".disabled, :disabled"))return;var d=f(c),g=d.hasClass("open");e();if(!g){"ontouchstart"in document.documentElement&&!d.closest(".navbar-nav").length&&a('