├── .github
├── dependabot.yml
└── workflows
│ ├── a10rest-docker-image.yml
│ ├── android.yml
│ └── codeql-analysis.yml
├── .gitignore
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── LICENSE
├── README.md
├── configs-docker
├── config.yaml
├── mosquitto.conf
└── sgx_default_qcnl.conf
├── dist
├── config.yaml
├── ga10.service
├── make_distribution.sh
├── ta10.service
├── temporary.crt
└── temporary.key
├── docker-compose.yml
├── docs
├── automaticStartup.md
├── compiling.md
├── contents.md
├── history.md
├── ignore
│ ├── example_EPEV.md
│ ├── ga10OldREADME.md
│ └── miscstuff.md
├── publications.md
├── running.md
└── security.md
├── ga10
├── .vscode
│ └── launch.json
├── Dockerfile
├── config.yaml
├── configuration
│ └── configuration.go
├── datalayer
│ ├── count.go
│ ├── initialisation.go
│ ├── internaldbs.go
│ ├── mongo.go
│ └── mqtt.go
├── enclave.json
├── ga10.go
├── go.mod
├── go.sum
├── logging
│ └── logging.go
├── operations
│ ├── attestation.go
│ ├── claims.go
│ ├── elements.go
│ ├── expectedValues.go
│ ├── log.go
│ ├── opaqueobjects.go
│ ├── operrors.go
│ ├── policies.go
│ ├── protocols.go
│ ├── results.go
│ ├── rules.go
│ ├── sessions.go
│ ├── signingFunctions.go
│ └── verification.go
├── otherconfigfiles
│ ├── local.yaml
│ └── nconfig.yaml
├── protocols
│ ├── a10httprestv2
│ │ └── public.go
│ ├── marblerun
│ │ └── public.go
│ ├── netconfprotocol
│ │ └── public.go
│ ├── nullprotocol
│ │ └── public.go
│ ├── registerProtocols.go
│ └── testcontainerprotocol
│ │ └── public.go
├── rules
│ ├── keylime
│ │ └── public.go
│ ├── marblerun
│ │ └── public.go
│ ├── nullrule
│ │ └── public.go
│ ├── registerRules.go
│ ├── sysrules
│ │ └── public.go
│ ├── testcontainerrules
│ │ └── public.go
│ └── tpm2rules
│ │ └── public.go
├── services
│ ├── restapi
│ │ ├── endpointOpaqueObjects.go
│ │ ├── endpointsAttestVerify.go
│ │ ├── endpointsClaims.go
│ │ ├── endpointsElements.go
│ │ ├── endpointsExpectedValues.go
│ │ ├── endpointsHealth.go
│ │ ├── endpointsLog.go
│ │ ├── endpointsPolicies.go
│ │ ├── endpointsProtocols.go
│ │ ├── endpointsResults.go
│ │ ├── endpointsRules.go
│ │ ├── endpointsSession.go
│ │ ├── initrestapi.go
│ │ └── resterrors.go
│ ├── webui
│ │ ├── attest.go
│ │ ├── claims.go
│ │ ├── elements.go
│ │ ├── expectedvalues.go
│ │ ├── homepages.go
│ │ ├── initwebapi.go
│ │ ├── log.go
│ │ ├── opaqueobjects.go
│ │ ├── policies.go
│ │ ├── protocols.go
│ │ ├── results.go
│ │ ├── rules.go
│ │ ├── sessions.go
│ │ ├── templatefunctions.go
│ │ └── templates
│ │ │ ├── about.html
│ │ │ ├── attest.html
│ │ │ ├── attestsummary.html
│ │ │ ├── base.html
│ │ │ ├── claim.html
│ │ │ ├── claim_ERROR.html
│ │ │ ├── claim_ima.html
│ │ │ ├── claim_quote.html
│ │ │ ├── claim_tpm2pcrs.html
│ │ │ ├── claims.html
│ │ │ ├── editelement.html
│ │ │ ├── editexpectedvalue.html
│ │ │ ├── editpolicy.html
│ │ │ ├── element.html
│ │ │ ├── elements.html
│ │ │ ├── elementsummarylist.html
│ │ │ ├── ev.html
│ │ │ ├── evs.html
│ │ │ ├── evsummarylist.html
│ │ │ ├── genericList.html
│ │ │ ├── help.html
│ │ │ ├── home.html
│ │ │ ├── hostinformation.html
│ │ │ ├── ima.html
│ │ │ ├── log.html
│ │ │ ├── opaqueobject.html
│ │ │ ├── opaqueobjects.html
│ │ │ ├── policies.html
│ │ │ ├── policy.html
│ │ │ ├── policysummarylist.html
│ │ │ ├── protocols.html
│ │ │ ├── result.html
│ │ │ ├── results.html
│ │ │ ├── resultvalue.html
│ │ │ ├── rules.html
│ │ │ ├── scraps
│ │ │ ├── session.html
│ │ │ ├── sessions.html
│ │ │ ├── tpm2.html
│ │ │ ├── tpm2key.html
│ │ │ ├── txt.html
│ │ │ └── uefi.html
│ └── x3270
│ │ ├── initx3270.go
│ │ ├── screenrules.go
│ │ └── screens.go
├── structures
│ ├── claims.go
│ ├── common.go
│ ├── elements.go
│ ├── expectedValues.go
│ ├── logs.go
│ ├── opaqueobjects.go
│ ├── policies.go
│ ├── protocols.go
│ ├── results.go
│ ├── rules.go
│ ├── sessions.go
│ └── types.go
├── temporary.crt
├── temporary.key
├── tests
│ ├── exampledatabase
│ │ ├── elements.json
│ │ ├── expectedvalues.json
│ │ └── policies.json
│ ├── p11test
│ │ ├── p.go
│ │ └── yubihsm_pkcs11.conf
│ ├── pkcs11test
│ │ ├── go.mod
│ │ ├── go.sum
│ │ ├── p.go
│ │ └── yubihsm_pkcs11.conf
│ └── testscripts
│ │ ├── attest.sh
│ │ ├── get.sh
│ │ ├── verify_laptop.sh
│ │ └── verify_pi.sh
└── utilities
│ ├── hashes.go
│ ├── identifiers.go
│ ├── timestamps.go
│ └── tpm.go
├── scripts
├── att.sh
└── attAutomation
│ ├── CreateElements.sh
│ ├── GenerateKeys.sh
│ ├── README.txt
│ ├── VerifyElements.sh
│ ├── attest.py
│ ├── closeSession.py
│ ├── createElement.py
│ ├── createExpected.py
│ ├── createKeys.py
│ ├── createSession.py
│ ├── elements.txt
│ ├── ga10pythonlib.py
│ └── verify.py
└── ta10
├── common
├── identifiers.go
└── unsafemode.go
├── go.mod
├── go.sum
├── ima
└── endpoints.go
├── sys
└── endpoints.go
├── ta10.go
├── tpm2
├── endpointstpm2.go
├── opentpm_unix.go
└── opentpm_windows.go
└── uefi
└── endpoints.go
/.github/dependabot.yml:
--------------------------------------------------------------------------------
1 | # To get started with Dependabot version updates, you'll need to specify which
2 | # package ecosystems to update and where the package manifests are located.
3 | # Please see the documentation for all configuration options:
4 | # https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
5 |
6 | version: 2
7 | updates:
8 | - package-ecosystem: "" # See documentation for possible values
9 | directory: "/" # Location of package manifests
10 | schedule:
11 | interval: "weekly"
12 |
--------------------------------------------------------------------------------
/.github/workflows/a10rest-docker-image.yml:
--------------------------------------------------------------------------------
1 | name: Docker Image CI
2 |
3 | on:
4 | push:
5 | branches: [ main ]
6 | pull_request:
7 | branches: [ main ]
8 |
9 | jobs:
10 |
11 | build:
12 |
13 | runs-on: ubuntu-latest
14 |
15 | steps:
16 | - uses: actions/checkout@v3
17 | - name: Build the Docker image
18 | run: docker build --file a10rest/Dockerfile.local --tag a10rest:$(date +%s) --output type=local,dest=a10rest.build.output .
19 | - uses: slsa-framework/github-actions-demo@v0.1
20 | with:
21 | artifact_path: a10rest.build.output
22 | output_path: a10rest.provenance
23 | continue-on-error: true
24 |
--------------------------------------------------------------------------------
/.github/workflows/android.yml:
--------------------------------------------------------------------------------
1 | name: Android CI
2 |
3 | on:
4 | push:
5 | branches: [main]
6 | pull_request:
7 | branches: [main]
8 |
9 | jobs:
10 | build:
11 | runs-on: ubuntu-latest
12 |
13 | steps:
14 | - uses: actions/checkout@v2
15 | - name: set up JDK 11
16 | uses: actions/setup-java@v2
17 | with:
18 | java-version: "11"
19 | distribution: "adopt"
20 | cache: gradle
21 | - name: Grant execute permission for gradlew
22 | working-directory: ./apps/mobileattester
23 | run: chmod +x gradlew
24 |
25 | - name: Run lint
26 | working-directory: ./apps/mobileattester
27 | run: ./gradlew lintDebug
28 | - name: Upload html test report
29 | uses: actions/upload-artifact@v2
30 | with:
31 | name: lint.html
32 | path: ./apps/mobileattester/app/build/reports/lint-results-debug.html
33 |
34 | - name: Build with Gradle
35 | working-directory: ./apps/mobileattester
36 | run: ./gradlew build
37 |
38 | test:
39 | needs: [build]
40 | name: Run Unit Tests
41 | runs-on: ubuntu-latest
42 | steps:
43 | - uses: actions/checkout@v2
44 | - name: set up JDK 11
45 | uses: actions/setup-java@v2
46 | with:
47 | java-version: "11"
48 | distribution: "adopt"
49 | cache: gradle
50 | - name: Run unit tests
51 | working-directory: ./apps/mobileattester
52 | run: bash ./gradlew test --stacktrace
53 |
54 | apk:
55 | needs: [test]
56 | name: Generate APK
57 | runs-on: ubuntu-latest
58 | steps:
59 | - name: Checkout
60 | uses: actions/checkout@v2
61 | - name: set up JDK 1.8
62 | uses: actions/setup-java@v1
63 | with:
64 | java-version: 11
65 | - name: Grant execute permission for gradlew
66 | working-directory: ./apps/mobileattester
67 | run: chmod +x gradlew
68 | - name: Build APK
69 | working-directory: ./apps/mobileattester
70 | run: ./gradlew assembleDebug
71 | - name: Upload APK
72 | uses: actions/upload-artifact@v2
73 | with:
74 | name: app
75 | path: ./apps/mobileattester/app/build/outputs/apk/debug/app-debug.apk
76 |
--------------------------------------------------------------------------------
/.github/workflows/codeql-analysis.yml:
--------------------------------------------------------------------------------
1 | # For most projects, this workflow file will not need changing; you simply need
2 | # to commit it to your repository.
3 | #
4 | # You may wish to alter this file to override the set of languages analyzed,
5 | # or to provide custom queries or build logic.
6 | #
7 | # ******** NOTE ********
8 | # We have attempted to detect the languages in your repository. Please check
9 | # the `language` matrix defined below to confirm you have the correct set of
10 | # supported CodeQL languages.
11 | #
12 | name: "CodeQL"
13 |
14 | on:
15 | push:
16 | branches: [ main ]
17 | pull_request:
18 | # The branches below must be a subset of the branches above
19 | branches: [ main ]
20 | schedule:
21 | - cron: '33 14 * * 5'
22 |
23 | jobs:
24 | analyze:
25 | name: Analyze
26 | runs-on: ubuntu-latest
27 | permissions:
28 | actions: read
29 | contents: read
30 | security-events: write
31 |
32 | strategy:
33 | fail-fast: false
34 | matrix:
35 | language: [ 'go', 'javascript', 'python' ]
36 | # CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
37 | # Learn more about CodeQL language support at https://git.io/codeql-language-support
38 |
39 | steps:
40 | - name: Checkout repository
41 | uses: actions/checkout@v2
42 |
43 | # Initializes the CodeQL tools for scanning.
44 | - name: Initialize CodeQL
45 | uses: github/codeql-action/init@v1
46 | with:
47 | languages: ${{ matrix.language }}
48 | # If you wish to specify custom queries, you can do so here or in a config file.
49 | # By default, queries listed here will override any specified in a config file.
50 | # Prefix the list here with "+" to use these queries and those in the config file.
51 | # queries: ./path/to/local/query, your-org/your-repo/queries@main
52 |
53 | # Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
54 | # If this step fails, then you should remove it and run the build manually (see below)
55 | - name: Autobuild
56 | uses: github/codeql-action/autobuild@v1
57 |
58 | # ℹ️ Command-line programs to run using the OS shell.
59 | # 📚 https://git.io/JvXDl
60 |
61 | # ✏️ If the Autobuild fails above, remove it and uncomment the following three lines
62 | # and modify them (or add more) to build your code if your project
63 | # uses a compiled language
64 |
65 | #- run: |
66 | # make bootstrap
67 | # make release
68 |
69 | - name: Perform CodeQL Analysis
70 | uses: github/codeql-action/analyze@v1
71 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Welcome
2 |
3 | Welcome to the Nokia Attestation Engine. See the README.md for more information and INSTALL.md here in the root directory for how to install using docker. In the u10 and a10rest directories you'll find the README.md files there on how to start the components without docker.
4 |
5 | In the A10 directory you'll find the installation instructions for building the python libraries and how to deploy these locally.
6 |
7 | # Submitting Changes
8 |
9 | Fork, make a pull request, push and notify me
10 |
11 | # Bugs, Enhancements and Missing Features
12 |
13 | There are lots of these. Use the issue tracker on github.
14 |
15 | I can't promise all features will be implemented nor all bugs fixed, but there are quite a few places where things could be improvied.
16 |
17 | Please remember that this software was build to explore ideas so things such as security, logins etc where not considered.
18 |
19 | # Thanks
20 |
21 | Huge thanks to anyone who provides feedback!
22 |
23 | # Getting Help
24 |
25 | Github issue tracker would be the best place - We'll be reading this fairly often. If things need more discussion then we can move to email on a case-by-case basis.
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The Clear BSD License
2 |
3 | Copyright (c) 2021 Nokia
4 | All rights reserved.
5 |
6 | Redistribution and use in source and binary forms, with or without
7 | modification, are permitted (subject to the limitations in the disclaimer
8 | below) provided that the following conditions are met:
9 |
10 | * Redistributions of source code must retain the above copyright notice,
11 | this list of conditions and the following disclaimer.
12 |
13 | * Redistributions in binary form must reproduce the above copyright
14 | notice, this list of conditions and the following disclaimer in the
15 | documentation and/or other materials provided with the distribution.
16 |
17 | * Neither the name of the copyright holder nor the names of its
18 | contributors may be used to endorse or promote products derived from this
19 | software without specific prior written permission.
20 |
21 | NO EXPRESS OR IMPLIED LICENSES TO ANY PARTY'S PATENT RIGHTS ARE GRANTED BY
22 | THIS LICENSE. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND
23 | CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
24 | LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
25 | PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR
26 | CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
27 | EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
28 | PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
29 | BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER
30 | IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
31 | ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
32 | POSSIBILITY OF SUCH DAMAGE.
33 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # A10 - Nokia Attestation Engine
2 |
3 | This is the source for the Nokia Attestation Engine A10.
4 |
5 | This software is used as the remote attestation engine as part of a trusted and/or confidential computing environment. This is the system that holds the known good values about devices and other elements, and provides the attestation and validation mechanisms.
6 |
7 | The software here is provided as-is - there is no security (http for the win!) and the error checking in places is completely missing. The point of this was to explore more interesting mechanisms for remote attestation and to implement ideas from the IEFT RATS specification. *READ* the security section!!!
8 |
9 | Refer to the [contents](docs/contents.md) in the `docs` directory.
--------------------------------------------------------------------------------
/configs-docker/config.yaml:
--------------------------------------------------------------------------------
1 | #Some general naming
2 | system:
3 | name: ASVR_GO_1
4 |
5 | #MongoDB Configuration
6 | database:
7 | connection: mongodb://mongodb:27017
8 | name: testasvrlocal
9 |
10 | #MQTT Configuration
11 | messaging:
12 | broker: messagebus
13 | port: 1883
14 | clientid: asvrgo1
15 |
16 | #REST Interface Configuration
17 | rest:
18 | port: 8520
19 | crt: temporary.crt
20 | key: temporary.key
21 | usehttp: false
22 |
23 | #Web Interface Configuration
24 | web:
25 | port: 8540
26 | crt: temporary.crt
27 | key: temporary.key
28 | usehttp: true
29 |
30 |
31 | #Web Interface Configuration
32 | x3270:
33 | port: 3270
34 |
35 |
36 | #Log file
37 | logging:
38 | logfilelocation: /tmp/ga10.log
39 | sessionupdatelogging: false
40 |
41 | #Keylime
42 | keylime:
43 | apiurl: "http://keylime:8080"
--------------------------------------------------------------------------------
/configs-docker/mosquitto.conf:
--------------------------------------------------------------------------------
1 | listener 1883
2 | allow_anonymous true
3 |
--------------------------------------------------------------------------------
/dist/config.yaml:
--------------------------------------------------------------------------------
1 | #Some general naming
2 | system:
3 | name: ASVR_GO_1
4 |
5 | #MongoDB Configuration
6 | database:
7 | connection: mongodb://192.168.1.203:27017
8 | name: test1
9 |
10 | #MQTT Configuration
11 | messaging:
12 | broker: 192.168.1.203
13 | port: 1883
14 | clientid: asvrgo1
15 |
16 | #REST Interface Configuration
17 | rest:
18 | port: 8520
19 | crt: temporary.crt
20 | key: temporary.key
21 | usehttp: false
22 |
23 | #Web Interface Configuration
24 | web:
25 | port: 8540
26 | crt: temporary.crt
27 | key: temporary.key
28 | usehttp: true
29 |
30 | #x3270 Configuraiton
31 | x3270:
32 | port: 3270
33 |
34 | #D10 Service Configuration
35 | d10:
36 | port: 8521
37 | files: /var/ga10/d10
38 |
39 | #Log file
40 | logging:
41 | logfilelocation: /tmp/ga10.log
42 | sessionupdatelogging: false
43 |
--------------------------------------------------------------------------------
/dist/ga10.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=GA10 Attestation Engine
3 | After=network.target
4 | StartLimitIntervalSec=0
5 |
6 | [Service]
7 | Type=simple
8 | Restart=always
9 | RestartSec=1
10 | User=ian
11 | ExecStart=/opt/nae/ga10 -config=/opt/nae/ga10config.yaml
12 |
13 | [Install]
14 | WantedBy=multi-user.target
--------------------------------------------------------------------------------
/dist/make_distribution.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash +x
2 |
3 | echo "Making distribution binaries"
4 |
5 | DISTDIR=/tmp
6 | GA10_BINARY_NAME=ga10
7 | TA10_BINARY_NAME=ta10
8 |
9 | DATE=`date +%s%3N`
10 | LD_RELEASE_FLAGS="-X main.BUILD=$DATE"
11 |
12 | echo "Binary release code is " $DATE
13 |
14 | echo "Making ga10"
15 |
16 | cd ../ga10
17 | go get -u
18 | go mod tidy
19 |
20 | GOOS=linux GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${GA10_BINARY_NAME}_linuxamd64 ga10.go
21 | GOOS=linux GOARCH=arm64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${GA10_BINARY_NAME}_linuxarm64 ga10.go
22 | GOOS=linux GOARCH=arm go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${GA10_BINARY_NAME}_linuxarm32 ga10.go
23 |
24 | GOOS=illumos GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${GA10_BINARY_NAME}_illumosamd64 ga10.go
25 | GOOS=windows GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${GA10_BINARY_NAME}_windowsamd64 ga10.go
26 | GOOS=openbsd GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${GA10_BINARY_NAME}_openBSDamd64 ga10.go
27 | GOOS=freebsd GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${GA10_BINARY_NAME}_freeBSDamd64 ga10.go
28 |
29 | cd ../ta10
30 | go get -u
31 | go mod tidy
32 |
33 | GOOS=linux GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${TA10_BINARY_NAME}_linuxamd64 ta10.go
34 | GOOS=linux GOARCH=arm64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${TA10_BINARY_NAME}_linuxarm64 ta10.go
35 | GOOS=linux GOARCH=arm go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${TA10_BINARY_NAME}_linuxarm32 ta10.go
36 |
37 | GOOS=illumos GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${TA10_BINARY_NAME}_illumosamd64 ta10.go
38 | GOOS=windows GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${TA10_BINARY_NAME}_windowsamd64 ta10.go
39 | GOOS=openbsd GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${TA10_BINARY_NAME}_openBSDamd64 ta10.go
40 | GOOS=freebsd GOARCH=amd64 go build -ldflags="${LD_RELEASE_FLAGS}" -o $DISTDIR/${TA10_BINARY_NAME}_freeBSDamd64 ta10.go
41 |
42 | echo "Listing binaries"
43 |
44 | cd $DISTDIR
45 | ls -l ga10_* ta10_*
46 |
47 | echo "SHA256 Values"
48 |
49 | sha256sum $DISTDIR/${GA10_BINARY_NAME}_linuxamd64
50 | sha256sum $DISTDIR/${GA10_BINARY_NAME}_linuxarm64
51 | sha256sum $DISTDIR/${GA10_BINARY_NAME}_linuxarm32
52 | sha256sum $DISTDIR/${GA10_BINARY_NAME}_illumosamd64
53 | sha256sum $DISTDIR/${GA10_BINARY_NAME}_windowsamd64
54 | sha256sum $DISTDIR/${GA10_BINARY_NAME}_openBSDamd64
55 | sha256sum $DISTDIR/${GA10_BINARY_NAME}_freeBSDamd64
56 | sha256sum $DISTDIR/${TA10_BINARY_NAME}_linuxamd64
57 | sha256sum $DISTDIR/${TA10_BINARY_NAME}_linuxarm64
58 | sha256sum $DISTDIR/${TA10_BINARY_NAME}_linuxarm32
59 | sha256sum $DISTDIR/${TA10_BINARY_NAME}_illumosamd64
60 | sha256sum $DISTDIR/${TA10_BINARY_NAME}_windowsamd64
61 | sha256sum $DISTDIR/${TA10_BINARY_NAME}_openBSDamd64
62 | sha256sum $DISTDIR/${TA10_BINARY_NAME}_freeBSDamd64
63 |
64 |
65 | echo "Done."
--------------------------------------------------------------------------------
/dist/ta10.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description=TA10 Trust Agent
3 | After=network.target
4 | StartLimitIntervalSec=0
5 |
6 | [Service]
7 | Type=simple
8 | Restart=always
9 | RestartSec=1
10 | User=root
11 | ExecStart=/opt/nae/ta10
12 |
13 | [Install]
14 | WantedBy=multi-user.target
--------------------------------------------------------------------------------
/dist/temporary.crt:
--------------------------------------------------------------------------------
1 | -----BEGIN CERTIFICATE-----
2 | MIID+TCCAuGgAwIBAgIUVJZap9c3I9vnPWzjuCdr2HzMn58wDQYJKoZIhvcNAQEL
3 | BQAwgYsxCzAJBgNVBAYTAkZJMRAwDgYDVQQIDAdVdXNpbWFhMQ4wDAYDVQQHDAVT
4 | aXBvbzESMBAGA1UECgwJQ2VmZnlsT3BpMQwwCgYDVQQLDANSJkQxDDAKBgNVBAMM
5 | A0lhbjEqMCgGCSqGSIb3DQEJARYbaWFuLmp1c3Rpbi5vbGl2ZXJAZ21haWwuY29t
6 | MB4XDTIzMDQyNDE2NDEyM1oXDTI0MDQyMzE2NDEyM1owgYsxCzAJBgNVBAYTAkZJ
7 | MRAwDgYDVQQIDAdVdXNpbWFhMQ4wDAYDVQQHDAVTaXBvbzESMBAGA1UECgwJQ2Vm
8 | ZnlsT3BpMQwwCgYDVQQLDANSJkQxDDAKBgNVBAMMA0lhbjEqMCgGCSqGSIb3DQEJ
9 | ARYbaWFuLmp1c3Rpbi5vbGl2ZXJAZ21haWwuY29tMIIBIjANBgkqhkiG9w0BAQEF
10 | AAOCAQ8AMIIBCgKCAQEAnYeTyopKf82aGAtACj3GFXBDyAqnOWz3t5P8x7mhU6TW
11 | /+RKbKIpV9/Gytg0hQOsXf5izjOqwu92RJA08W0iO6J/GNFEuYg3tf3MYtFmDZL7
12 | DtHicRY+apSgrv4NtpTezW0DHFdyLHK0RL32Fgkb9JRHfQdssRmymKu8PvPxyFw7
13 | HbD7MurORiGycl/oVdrRhws7lMF/kLuK+ksh3G6M/+sF/4HCtAJ37aeXRAnudktB
14 | RelkBd80HKebsbtPkwJrF1g5VpVBDgJVx28MfRrGLotiKwmAp1nVha6JcGZ6y3Sl
15 | BYTW96/g1QlxOC7tYef0QyyGDeAhIivSwlzuGZ3EzQIDAQABo1MwUTAdBgNVHQ4E
16 | FgQUhMNzN/omyGgTvG5jqDWtFN1G/lkwHwYDVR0jBBgwFoAUhMNzN/omyGgTvG5j
17 | qDWtFN1G/lkwDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAmB24
18 | b+ST3ds4pfdiAB6Xfenkk3Fo9cg4hDA9v1nQvXe49x9ZMq5yZ9tkOIWtI0y2nCky
19 | qUGbU08EuZmLyq7ReurRg2nMLi/M+xMJmaCzMMg8vQPMwcAy/EsDgVUS66rbWMYn
20 | VA/zLbjkNAXPzxYzVTSKVdw4loNLagoOkCZRYotA5w9LlmcC/5yxX9wJxb/K7CD7
21 | HPovpR1alU2J5vAbjmo/TAjRFzkt2pQ8kqjAmdWjJb/zIJWwv/s62obb/Ye9kZy4
22 | 40CejuNxsYIvkMyeNAAs6psDO/eEMQITvtaMakczM6qQpdX6yYdWnUOvvjOfu6YA
23 | k7nQ2CE2vEAiLhxZIQ==
24 | -----END CERTIFICATE-----
25 |
--------------------------------------------------------------------------------
/dist/temporary.key:
--------------------------------------------------------------------------------
1 | -----BEGIN PRIVATE KEY-----
2 | MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCdh5PKikp/zZoY
3 | C0AKPcYVcEPICqc5bPe3k/zHuaFTpNb/5EpsoilX38bK2DSFA6xd/mLOM6rC73ZE
4 | kDTxbSI7on8Y0US5iDe1/cxi0WYNkvsO0eJxFj5qlKCu/g22lN7NbQMcV3IscrRE
5 | vfYWCRv0lEd9B2yxGbKYq7w+8/HIXDsdsPsy6s5GIbJyX+hV2tGHCzuUwX+Qu4r6
6 | SyHcboz/6wX/gcK0Anftp5dECe52S0FF6WQF3zQcp5uxu0+TAmsXWDlWlUEOAlXH
7 | bwx9GsYui2IrCYCnWdWFrolwZnrLdKUFhNb3r+DVCXE4Lu1h5/RDLIYN4CEiK9LC
8 | XO4ZncTNAgMBAAECggEABlx/uNmdyYxtcRQfOWqmMZ5vdkgL2bNPS5AD0LLr01tg
9 | PUQkRz/DKKPGPNG/STHNR5xqtAX9GtMdtQYXxToRfFQDCucEffOEwGon00O+ecTa
10 | M46BNOzfh2FKHdbvidR4LNZ+ninf1/Cn2/DJ27jxco58Vo2ys3IktqqUtvwV4u/a
11 | Tozfc5BWlVd2eYqwv8MyhZPpPxcArC1vPH2os/1/Q/qe8IpCOBHy12SN7Nje+l3p
12 | LYRLHm3rHhKPwHIEd05d5S3BZ0u3Eea20hXAynT2483XaLj1QpImRRZ4O5H0RRRE
13 | apRU7hPlqD8kpD7g6kbkiMCJUOp2Q2NbzfPVH7hlFwKBgQDQKOnABlG5InHPE+su
14 | I1AlvGIThFPbKZEH4MSA3nNEeyqV2P7eRadZexJdF8BAS8yqp73ZbbqFeAkMtL2/
15 | gc4grOovr4BKy8S3w8utd82dqwD7dUxY+DcP57rogdz7Z82R+RpUwksitv8K1nDM
16 | JGo7WvDUDxQqnRs29WwFb+e9owKBgQDBu9WYeleUwl7krKW9+XmqzDcHwXik6udv
17 | 591IFNbW0B3XGweI18bvTmpYK1cYNYhamloawEiERofX+LVQGKsz33XdcP9a/k7E
18 | ADJy+begSjRvQ7SML3V+KGZSPKE2Wo5ohpBgy+ytFCUb0APC0K/Mk/kjLQHr/ZSg
19 | 5bDp3fG6zwKBgQCoe4T/JN4+v+9oEZI4bOKxOHIVo/SPnmxB+R5zxBl+I0bLtLBN
20 | zgju9xtc+B1mrTOCKXUTqKng39BLVXuDpxflALAoWp+3aojVyIdx51cot8F6xm0+
21 | UeGXYRO6n2nynwkXjo1Ob1iLR5zU886mnQ7S7f+hVHcZKsJdUHXXTMVAiwKBgDtU
22 | MJdfcA7Ib5MMJD3HdrENlRS09SNcJMAqe6Olbh2e4mSLjIUlv3BtzTdvHl71lepZ
23 | NprWo96OUu+a5LvAsj1Sg5/rCOhu1ORFQy3et5NI5kHktBfyOMMH0D4C/0PL+6ya
24 | +QALs1FVx/96doxkqFG4RyW0lNAWejvD26fjJjIVAoGAeP9pJPFIGFUpUwKTVgsJ
25 | cfm082bJsRpBvRWHhDvJA8nliY1XoTGzoproNxCeZLywkKREflGw2d9AeYgCo8OD
26 | z16VvR/B13l0Dh4fYQS7wGkGEJ2+LcKlEZ+lCWbrFNWHre8vZ9/capxB6PrPn10R
27 | N/cWWNE1DVBVVxu/83lsAk0=
28 | -----END PRIVATE KEY-----
29 |
--------------------------------------------------------------------------------
/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3.8'
2 | services:
3 | mongodb:
4 | image: mongo:6-jammy
5 | volumes:
6 | - db:/data/db
7 | messagebus:
8 | image: "eclipse-mosquitto"
9 | volumes:
10 | - ./configs-docker/mosquitto.conf:/mosquitto/config/mosquitto.conf
11 | keylime:
12 | image: keylime_base
13 | environment:
14 | KEYLIME_VERIFIER_MEASURED_BOOT_POLICY_NAME: "example"
15 | entrypoint: ["keylime_validation", "8080"]
16 | ga10:
17 | build:
18 | context: ./ga10
19 | dockerfile: Dockerfile
20 | entrypoint: /ga10 --config=/config.yaml
21 | ports:
22 | - 8520:8520
23 | - 8540:8540
24 | - 3270:3270
25 | volumes:
26 | - ./configs-docker/config.yaml:/config.yaml
27 | - ./ga10/temporary.crt:/temporary.crt
28 | - ./ga10/temporary.key:/temporary.key
29 | - ./configs-docker/sgx_default_qcnl.conf:/etc/sgx_default_qcnl.conf
30 | volumes:
31 | db:
--------------------------------------------------------------------------------
/docs/automaticStartup.md:
--------------------------------------------------------------------------------
1 | # Automatic Startup at Boot
2 |
3 | In this section we present an example distribution for use in a systemd environment. We utilise the file layout given in the follow section.
4 |
5 | ## Example File Layout (Linux/BSD)
6 |
7 | One possible layout is to put everything in `/opt`. Note, `ga10` and `ta10` are put together just for convenience. Set permissions accordingly.
8 |
9 | ```bash
10 | $ pwd
11 | /opt/nae
12 | $ ls -l
13 | total 27364
14 | -rw-rw-r-- 1 ian ian 706 tammi 21 13:01 config.yaml
15 | -rwxrwxr-x 1 ian ian 19448208 tammi 21 13:00 ga10
16 | -rwxrwxr-x 1 ian ian 8554460 tammi 21 13:02 ta10
17 | -rw-rw-r-- 1 ian ian 1440 tammi 21 13:01 temporary.crt
18 | -rw-rw-r-- 1 ian ian 1704 tammi 21 13:01 temporary.key
19 | ```
20 |
21 | ## GA10 and Systemd on Linux
22 |
23 | Place the following systemd configuration in `/etc/systemd/system` as `ga10.service`
24 |
25 | ```
26 | [Unit]
27 | Description=GA10 Attestation Engine
28 | After=network.target
29 | StartLimitIntervalSec=0
30 |
31 | [Service]
32 | Type=simple
33 | Restart=always
34 | RestartSec=1
35 | User=ian
36 | ExecStart=/opt/nae/ga10 -config=/opt/nae/config.yaml
37 |
38 | [Install]
39 | WantedBy=multi-user.target
40 | ```
41 |
42 | Ensure the `config.yaml` is properly configured for your system and installation.
43 |
44 | Start with `systemctl start ga10.service` and enable with `systemctl enable ga10.service`. Use `journalctl -xe` to check startup and possible errors.
45 |
46 |
47 | ## TA10 and Systemd on Linux
48 |
49 | Place the following systemd configuration in `/etc/systemd/system` as `ta10.service`
50 |
51 | Note ta10 may require root to run. Take note of any security aspects.
52 |
53 | ```
54 | [Unit]
55 | Description=TA10 Trust Agent
56 | After=network.target
57 | StartLimitIntervalSec=0
58 |
59 | [Service]
60 | Type=simple
61 | Restart=always
62 | RestartSec=1
63 | User=root
64 | ExecStart=/opt/nae/ta10
65 |
66 | [Install]
67 | WantedBy=multi-user.target
68 | ```
69 |
70 | Start with `systemctl start ta10.service` and enable with `systemctl enable ta10.service`. Use `journalctl -xe` to check startup and possible errors.
71 |
72 | ## Windows
73 |
74 | This is possible. In respositor in `dist` is a file `ta10TrustAgent.xml` which provides some hints on this.
75 |
76 | ## BSD (rc.d)
77 |
78 | Yes too. This script placed in `/etc/rc.d` called `ta10` works for startup, at least on my OpenBSD VM:
79 |
80 | ```
81 | #!/bin/sh
82 | #
83 | # $OpenBSD: ta10
84 |
85 | daemon="/opt/nae/ta10"
86 |
87 | . /etc/rc.d/rc.subr
88 |
89 | rc_cmd $1
90 | ```
--------------------------------------------------------------------------------
/docs/compiling.md:
--------------------------------------------------------------------------------
1 | # Compiling
2 |
3 | Ensure that Go is installed and correctly configured. You will also need the Intel SGX SDK and Edgeless libraries.
4 |
5 | The instructions presented here have been tested in Ubuntu 22.04 om AMD64.
6 |
7 | ## Install SGX SDK and Edgeless
8 |
9 | Intel and Edgeless supply releases for Ubuntu and other operating systems. Here we should for Ubuntu Jammy (22.04). These commands might need to be run as `sudo`. Modify as appropriate for your operating system.
10 |
11 | ```bash
12 | mkdir -p /etc/apt/keyrings
13 | wget -q https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /etc/apt/keyrings/intel-sgx-keyring.asc
14 | echo "deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu jammy main" > /etc/apt/sources.list.d/intel-sgx.list
15 | apt update
16 | wget https://github.com/edgelesssys/edgelessrt/releases/download/v0.4.1/edgelessrt_0.4.1_amd64_ubuntu-22.04.deb
17 | apt-get install -y ./$ERT_DEB build-essential cmake libssl-dev libsgx-dcap-default-qpl libsgx-dcap-ql libsgx-dcap-quote-verify
18 | ```
19 |
20 | ## Compiling GA10
21 |
22 | Compilation requires an up-to-date mod file and the Edgeless environment variables - which should be installed if the above went correctly. *MAKE SURE* you are in the `ga10` directory when you run these commands:
23 |
24 | ```bash
25 | go get -u
26 | go mod tidy
27 | . /opt/edgelessrt/share/openenclave/openenclaverc && GOOS=linux GOARCH=amd64 go build -o ga10
28 | ```
29 |
30 | You will now get a file called `ga10` which is your executable.
31 |
32 | If you wish to reduce the size of the binary, run `strip ga10`
33 |
34 | ## Compiling TA10
35 |
36 | *MAKE SURE* you are in the `ta10` directory. TA10 is much simpler than ga10 and requires just compilation. For your local operating system and architecture you can remove the `GOOS` and `GOARCH` variables, for example as shown below. The `strip` command is optional but it does reduce the binary size a little.
37 |
38 | ```bash
39 | go get -u
40 | go mod tidy
41 | go build -o ta10
42 | strip ta10
43 | ```
44 |
45 | For other architectures, use `go tool dist list` for a list of operating system and architecture options. Listed below are a few common options - and we like to append this to the binary name when we're generating a few of these for the devices we have (remeber amd64 is 64-bit Intel/AMD x86 based chips, eg: Xeons, i9's, i7's, Threaripper etc etc)
46 |
47 | ```bash
48 | GOOS=linux GOARCH=arm go build -o ta10_arm # eg: Pi 3s
49 | GOOS=linux GOARCH=arm64 go build -o ta10_arm64 # eg: Pi 4, 5s in 64-bit mode (also 3's I think)
50 | GOOS=windows GOARCH=amd64 go build -o ta10_win # eg: Pretty much every Win10, Win11 machine
51 | GOOS=plan9 GOARCH=386 go build -o ta10_belllabs # Because we're Bell Labs....
52 | GOOS=linux GOARCH=s390x go build -o ta10_mainframe # Because you either have an z-Series in the basement or Hercules
53 | GOOS=solaris GOARCH=amd64 go build -o ta10_solaris # I still mourn the lost of the SparcStation and UltraSparcs, RIP Sun.
54 | GOOS=opebsd GOARCH=amd64 go build -o ta10_openbsd # BSD for security
55 | GOOS=freebsd GOARCH=amd64 go build -o ta10_freeebsd # More BSD fun
56 | GOOS=darmin GOARCH=arm64 go build -o ta10_mac # For the Apple people out there...no TPM, but if you figure out attesting a T2 let me know
57 | GOOS=aix GOARCH=ppc64 go build -o ta10_aix # If you have an AIX box, let me know...DRTM is supported during boot and a TPM too?
58 | ```
59 |
60 |
--------------------------------------------------------------------------------
/docs/contents.md:
--------------------------------------------------------------------------------
1 | # Contents
2 |
3 | ## Basics
4 |
5 | * [Compiling](compiling.md)
6 | * [Running](running.md)
7 | * [Automatic Startup](automaticStartup.md)
8 | * [Security and Running in a Producton Environment](security.md)
9 |
10 | ## Getting Started
11 |
12 | * Creating an element
13 | * Attesting and Verification
14 |
15 | ## Structures
16 |
17 | * Elements
18 | * Policies
19 | * Expected Values
20 | * Claims
21 | * Results
22 | * Sessions
23 |
24 | ## Evidence
25 |
26 | * Signing
27 |
28 | ## Protocols and Trust Agents
29 |
30 | * Protocols
31 | * Intents
32 | * Trust Agents and Endpoints
33 |
34 | ## Verification and Rules
35 |
36 | * Rules
37 |
38 | ## Appendicits
39 |
40 | * [History](history.md)
41 | * [Publications](publications.md)
--------------------------------------------------------------------------------
/docs/history.md:
--------------------------------------------------------------------------------
1 | # History
2 |
3 | The attestation engine has a long an varied history
4 |
5 | ## A1,A2 and A3
6 |
7 | Early experiments, circle late 2014, early 2015. Written in Javascript with lots of pain regarding reactive, functional programming
8 |
9 | ## A4
10 |
11 | First version that actually worked, also written in Javascript. Not very functional but there existed a trust agent for quoting and quite similar in functionality to systems such as OpenAttestation, Mt.Wilson, Charra and early Keylime.
12 |
13 | ## A5 and A6
14 |
15 | First versions in python 2 and some of the code here ended up in A7. Some parts of A5 and A6 integrated with OpenStack's workflow and workload manager APIs - which worked as long as you didn't update OpenStack as APIs changed randomly betweent versions.
16 |
17 | ## A7
18 |
19 | First properly working attestation server in a very traditional manner (cf: OpenAttestation etc). Written in a mix of python2 and python3. Backend utilised mongodb and assumed the TA talked directly to the tpm2_tools on the client. UI written using python flask. Integrated with OpenStack via a client which was a MITM/hack/kludge to access OpenStack's message bus. This version was demonstrated at ETSI SecurityWeek in 2018 and 2019. Contained a lot of technical debt which made integration hard in some cases.
20 |
21 | ## A8.1 and A8.2
22 |
23 | These were an attempt to write everything in Erlang, and simulaneously in python with threads, proceses and using MQTT for interprocess communication in a complete asynchronous way. I don't think the source coude even exists anymore.
24 |
25 | ## A9
26 |
27 | Was an experiment to use the ELKS analytics stack and the ELKS UI. Was demonstrated in January 2020 for the first time and actively developed for about 6 months until we needed to support new features. Much of this work reappears as plugins and data integration (as attesation apps in A10) into ELKS and ELKS-based tools such as Nokia's NetGuard.
28 |
29 | ## A10
30 |
31 | A much more compliant with IEFT RATS in its data structures. Has a proper protocol backend which takes care of layer 7 and layer 6 of the attestation protocols so we can theoretically support any RoT/auditing system, eg: HSM, UEFI, TPM2.0, TPM1.2 etc, we can even integrate with other attestation engines' trust agents such as KeyLime, OpenAttestation, Go-Attestation etc. Libraries are much better written with a much more consistent API. UI and interfaces are separate components built on top of libraries. The whole thing is designed to integrate with MQTT, logstash, ELKS, whatever AI/ML analytics and the forensics system that is currently under development. Lots of cool features. Supports the notion of *attestation applications** for extensibility making integration with other systems such as Edge/NFV MANO very quick and easy.
32 |
33 | ## GA10
34 |
35 | Even more compliant with IEFT RATS in its data structures and an improved protocol backend which takes care of layer 7 and layer 6 of the attestation protocols. All the cool stuff of A10 but now written in *Go*. Seriously strong typing is so important....Reworked UI, reworked REST API and reworked data structures. Oh so much better. AND, Go has a really nice cross compiler: arm, arm64, i386, amd64, ppc, and then Linux, Windows, Solaris, AIX and Plan 9 from Bell Labs. Also Go makes self-contained binaries so the trust agent is a single binary which makes distribution trivial and the whole server engine itself just needs the binary and the config file :-)
36 |
37 | Includes rules for working with confidential computing structures too.
--------------------------------------------------------------------------------
/docs/ignore/ga10OldREADME.md:
--------------------------------------------------------------------------------
1 | To build
2 |
3 | make build
4 | make distribution
5 | make
6 |
7 | go build .
8 | ./a10 --config=config.yaml --runtests=True
9 |
10 |
11 | To run (without build)
12 |
13 | go run . --config=config.yaml --runtests=True
14 |
15 |
16 | To set build version numbers for releases
17 |
18 | go build -ldflags="-X 'main.BUILD=123'"
19 |
20 | with a datetime
21 |
22 | go build -ldflags="-X 'main.BUILD=`date`'"
23 |
24 |
25 |
26 | To generate HTTPS keys
27 |
28 | openssl genrsa 2048 > temporary.key
29 | chmod 400 temporary.key
30 | openssl req -new -x509 -nodes -sha256 -days 365 -key temporary.key -out temporary.crt
31 |
32 |
33 |
34 |
35 | To reduce binary size
36 |
37 | ian@ian-virtual-machine:~/ga10$ go build -ldflags "-w" .
38 | ian@ian-virtual-machine:~/ga10$ ls -l a10
39 | -rwxrwxr-x 1 ian ian 13545955 huhti 25 15:37 a10
40 | ian@ian-virtual-machine:~/ga10$ go build -ldflags "-s -w" .
41 | ian@ian-virtual-machine:~/ga10$ ls -l a10
42 | -rwxrwxr-x 1 ian ian 12517376 huhti 25 15:38 a10
43 | ian@ian-virtual-machine:~/ga10$
44 |
45 |
46 | Installation
47 |
48 | NB: choose the correct operating system and architecture
49 |
50 | make distribution
51 | cp dist/a10_linuxamd64 /usr/local/bin/a10
52 | cp config.yaml /etc/a10config.yaml
53 | cp a10.service to /etc/systemd/system
54 |
55 | Modify the config.yaml file
56 |
57 | sudo systemctl daemon-reload
58 | sudo systemctl start a10.service
59 | journalctl -xe
60 |
61 | sudo systemctl stop a10.service
62 |
63 |
64 | sudo systemctl enable a10.service
65 |
66 | sudo systemctl disable a10.service
67 |
68 |
69 |
70 |
71 | PKCS#11
72 |
73 | Find the yubihsm.so file
74 | $ ls /usr/lib/x86_64-linux-gnu/pkcs11/
75 | gnome-keyring-pkcs11.so p11-kit-client.so p11-kit-trust.so yubihsm_pkcs11.so
76 |
77 | github.com/miekg/pkcs11
78 |
79 | Or which ever user can see the YubiHSM (sudo is probably not good)
80 | sudo yubihsm-connector -d
81 |
82 | specify where the yubihsm conf file is
83 | export YUBIHSM_PKCS11_CONF=/home/ian/pkcs11test/yubihsm_pkcs1.conf
84 |
--------------------------------------------------------------------------------
/docs/ignore/miscstuff.md:
--------------------------------------------------------------------------------
1 |
2 | To encryption in Go
3 | levelup.gitconnected.com/a-guide-to-rsa-encryption-in-go-1a18d827f35d
--------------------------------------------------------------------------------
/docs/security.md:
--------------------------------------------------------------------------------
1 | # Security
2 |
3 | Read carefully:
4 |
5 | * A self-signed key is provided called temporary.key/crt - DO NOT USE THIS IN PRODUCTION OR ANYWHERE. Browsers will complain if you use this.
6 | * THIS IS NOT SECURE!!!
7 | * PUTTING PRIVATE KEYS ON GITHUB FOR ANYTHING ELSE THAN A DEMONSTRATION IS CRAZY. DO NOT DO THIS.
8 | * TO SAVE YOURSELF, SET THE use http FIELDS TO true in the configuration file.
9 | * That isn't secure either...
10 | * GENERATE YOUR OWN KEYS AND KEEP THEM SECURE and use https
11 | * TA10 runs over HTTP !!!!
12 | * DO NOT USE TA10 IN UNSAFE MODE !!! (Even if you're not root!)
13 | * A10 signs claims, results, sessions etc...the keys are randomly generated each him the system is started and aren't recorded anywhere. There is some code to talk PKCS#11 and has been tested with a YubiHSM but it isn't used. Don't rely upon it, I haven't tested it and it is just placeholder at this time. Yes, I'll get arund to writing the proper functionality real soon now...volunteers?
14 |
15 | Now read the section on the use of this software in a production environment.
16 |
17 | # Use in a Production Environment
18 |
19 | Don't. This is not secure and many points where errors and exceptions should be captured are not implemented.
20 |
21 |
22 |
--------------------------------------------------------------------------------
/ga10/.vscode/launch.json:
--------------------------------------------------------------------------------
1 | {
2 | // Use IntelliSense to learn about possible attributes.
3 | // Hover to view descriptions of existing attributes.
4 | // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5 | "version": "0.2.0",
6 | "configurations": [
7 |
8 |
9 |
10 | {
11 | "name": "Launch Package",
12 | "type": "go",
13 | "request": "launch",
14 | "mode": "auto",
15 | "program": "${fileDirname}"
16 | }
17 | ]
18 | }
--------------------------------------------------------------------------------
/ga10/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:1.21-bookworm AS build
2 |
3 |
4 | RUN mkdir -p /etc/apt/keyrings && \
5 | wget -q https://download.01.org/intel-sgx/sgx_repo/ubuntu/intel-sgx-deb.key -O /etc/apt/keyrings/intel-sgx-keyring.asc && \
6 | echo "deb [signed-by=/etc/apt/keyrings/intel-sgx-keyring.asc arch=amd64] https://download.01.org/intel-sgx/sgx_repo/ubuntu jammy main" > /etc/apt/sources.list.d/intel-sgx.list && \
7 | apt update && \
8 | ERT_DEB=edgelessrt_0.4.1_amd64_ubuntu-22.04.deb && \
9 | wget https://github.com/edgelesssys/edgelessrt/releases/download/v0.4.1/$ERT_DEB && \
10 | apt-get install -y ./$ERT_DEB build-essential cmake libssl-dev libsgx-dcap-default-qpl libsgx-dcap-ql libsgx-dcap-quote-verify
11 |
12 | # Set destination for COPY
13 | WORKDIR /app
14 |
15 | # Download Go modules
16 | COPY ./go.mod ./go.sum ./
17 | RUN go mod download
18 |
19 | COPY . ./
20 |
21 | RUN go get -u
22 | RUN go mod tidy
23 | RUN . /opt/edgelessrt/share/openenclave/openenclaverc && GOOS=linux GOARCH=amd64 go build -o /ga10 ga10.go
24 |
25 | CMD ["/ga10"]
--------------------------------------------------------------------------------
/ga10/config.yaml:
--------------------------------------------------------------------------------
1 | #Some general naming
2 | system:
3 | name: ASVR_GO_1
4 |
5 | #MongoDB Configuration
6 | database:
7 | connection: mongodb://127.0.0.1:27017
8 | name: testasvrlocal
9 |
10 | #MQTT Configuration
11 | messaging:
12 | broker: 127.0.0.1
13 | port: 1883
14 | clientid: asvrgo1
15 |
16 | #REST Interface Configuration
17 | rest:
18 | port: 8520
19 | crt: temporary.crt
20 | key: temporary.key
21 | usehttp: false
22 |
23 | #Web Interface Configuration
24 | web:
25 | port: 8540
26 | crt: temporary.crt
27 | key: temporary.key
28 | usehttp: true
29 |
30 |
31 | #Web Interface Configuration
32 | x3270:
33 | port: 3270
34 |
35 |
36 | #Log file
37 | logging:
38 | logfilelocation: /tmp/ga10.log
39 | sessionupdatelogging: false
40 |
--------------------------------------------------------------------------------
/ga10/configuration/configuration.go:
--------------------------------------------------------------------------------
1 | package configuration
2 |
3 | import (
4 | "fmt"
5 | "io/ioutil"
6 |
7 | "gopkg.in/yaml.v3"
8 | )
9 |
10 | // The configuration structure also gives the format of the YAML config file
11 | //
12 | // For example
13 | //#Some general naming
14 | //system:
15 | // name: ASVR_GO_1 -- name of the ASVR system. Can be anything sensible
16 | //
17 | //#MongoDB Configuration
18 | //database:
19 | // connection: mongodb://192.168.1.203:27017 -- connection string for the mongodb
20 | // name: test1 -- name of the database to use
21 | //
22 | //#MQTT Configuration
23 | //messaging:
24 | // broker: 192.168.1.203 -- IP address of the MQTT broker
25 | // port: 1883 -- Port to use, typically 1883
26 | //
27 | //#REST Interface Configuration
28 | //rest:
29 | // port: 8520 -- Port to use for the REST API, default is 8520
30 | // crt: temporary.crt -- File containing the certificate to use for the HTTPS server
31 | // key: temporary.key -- File containing the private key for the HTTPS server
32 | // usehttp: true -- Use HTTP (true) instead of HTTPS. Default is false
33 |
34 | type ConfigurationStruct struct {
35 | System struct {
36 | Name string
37 | }
38 | Database struct {
39 | Connection string
40 | Name string
41 | }
42 | Messaging struct {
43 | Broker string
44 | Port uint16
45 | ClientID string
46 | }
47 | Rest struct {
48 | Port string
49 | Crt string
50 | Key string
51 | UseHTTP bool
52 | }
53 | Web struct {
54 | Port string
55 | Crt string
56 | Key string
57 | UseHTTP bool
58 | }
59 | X3270 struct {
60 | Port string
61 | }
62 | Logging struct {
63 | LogFileLocation string
64 | SessionUpdateLogging bool
65 | }
66 | Keylime struct {
67 | ApiUrl string
68 | }
69 | }
70 |
71 | // The exported variable for accessing the configuration structure
72 | var ConfigData *ConfigurationStruct
73 |
74 | // The function that reads the configuraiton file and sets up the configuration structure
75 | //
76 | // If the file is unavailable or in unparsable then this function will panic and exit.
77 | // There is no need to continue if the configuration is borked.
78 | func SetupConfiguration(f string) {
79 | fmt.Println("GA10: Configuration file location: ", f)
80 |
81 | configFile, err := ioutil.ReadFile(f)
82 | if err != nil {
83 | panic(fmt.Sprintf("Configuration file missing. Exiting with error ", err))
84 | }
85 |
86 | err = yaml.Unmarshal(configFile, &ConfigData)
87 | if err != nil {
88 | panic(fmt.Sprintf("Unable to parse configuration file. Exiting with error ", err))
89 | }
90 | }
91 |
--------------------------------------------------------------------------------
/ga10/datalayer/count.go:
--------------------------------------------------------------------------------
1 | package datalayer
2 |
3 | import(
4 | "context"
5 | "log"
6 | "reflect"
7 |
8 | // "go.mongodb.org/mongo-driver/mongo/options"
9 | "go.mongodb.org/mongo-driver/bson"
10 | )
11 |
12 | func Count(coll string) int64 {
13 | //options := options.Count()
14 | count, err := DB.Collection(coll).CountDocuments(context.TODO(), bson.D{})
15 |
16 | log.Printf("count for %v is %v %v, err is %v",coll,count,reflect.TypeOf(count),err)
17 |
18 | if err != nil {
19 | return -1
20 | } else {
21 | return count
22 | }
23 | }
--------------------------------------------------------------------------------
/ga10/datalayer/initialisation.go:
--------------------------------------------------------------------------------
1 | package datalayer
2 |
3 |
4 | func InitialiseDatalayer() {
5 |
6 | initialiseDatabase()
7 | initialiseMessaging()
8 | initialiseInternalDBs()
9 | }
--------------------------------------------------------------------------------
/ga10/datalayer/internaldbs.go:
--------------------------------------------------------------------------------
1 | package datalayer
2 |
3 | import(
4 | "a10/structures"
5 | )
6 |
7 | var RulesDatabase map[string]structures.Rule = make(map[string]structures.Rule)
8 | var ProtocolsDatabase map[string]structures.Protocol = make(map[string]structures.Protocol)
9 |
10 | func initialiseInternalDBs() {
11 | // No initialisation required as the current two internal databases are empty
12 | }
--------------------------------------------------------------------------------
/ga10/datalayer/mongo.go:
--------------------------------------------------------------------------------
1 | package datalayer
2 |
3 | import(
4 | "fmt"
5 | "context"
6 |
7 | "a10/configuration"
8 |
9 | "go.mongodb.org/mongo-driver/mongo"
10 | "go.mongodb.org/mongo-driver/mongo/options"
11 | )
12 |
13 | var DB *mongo.Database
14 | var DBCLIENT *mongo.Client
15 | var ctx = context.TODO()
16 |
17 |
18 |
19 | func initialiseDatabase() {
20 | fmt.Println("GA10: initialising database MONGO connection")
21 |
22 | clientOptions := options.Client().ApplyURI(configuration.ConfigData.Database.Connection)
23 | client, err := mongo.Connect(ctx, clientOptions)
24 |
25 | if err != nil {
26 | panic(err.Error())
27 | }
28 |
29 | err = client.Ping(ctx,nil)
30 | if err != nil {
31 | panic(err.Error())
32 | }
33 |
34 | DB = client.Database(configuration.ConfigData.Database.Name)
35 |
36 | fmt.Println("GA10: Database infrastructure MONGO is running")
37 |
38 | DBCLIENT = client
39 |
40 | }
--------------------------------------------------------------------------------
/ga10/datalayer/mqtt.go:
--------------------------------------------------------------------------------
1 | package datalayer
2 |
3 | import(
4 | "fmt"
5 |
6 | "a10/configuration"
7 |
8 | mqtt "github.com/eclipse/paho.mqtt.golang"
9 |
10 | )
11 |
12 | var MESSAGING mqtt.Client
13 |
14 | var connectHandler mqtt.OnConnectHandler = func(client mqtt.Client) {
15 | fmt.Println("GA10: MQTT connected")
16 | }
17 |
18 | var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) {
19 | fmt.Println("GA10: MQTT connection lost. Error %v",err)
20 | }
21 |
22 | func initialiseMessaging() {
23 | fmt.Println("GA10: Initialising message infrastructure MQTT connection")
24 |
25 | var broker = configuration.ConfigData.Messaging.Broker
26 | var port = configuration.ConfigData.Messaging.Port
27 |
28 | opts := mqtt.NewClientOptions()
29 | opts.AddBroker(fmt.Sprintf("tcp://%s:%d", broker, port))
30 | opts.SetClientID(configuration.ConfigData.Messaging.ClientID)
31 | //opts.SetUsername("me")
32 | //opts.SetPassword("me2")
33 | //opts.SetDefaultPublishHandler(messagePubHandler)
34 | opts.OnConnect = connectHandler
35 | opts.OnConnectionLost = connectLostHandler
36 |
37 | client := mqtt.NewClient(opts)
38 | if token := client.Connect(); token.Wait() && token.Error() != nil {
39 | fmt.Println("GA10: Failed to initialise MQTT connection")
40 | panic(token.Error())
41 | }
42 |
43 | fmt.Println("GA10: Message infrastructure MQTT is running")
44 |
45 | MESSAGING = client
46 | }
--------------------------------------------------------------------------------
/ga10/enclave.json:
--------------------------------------------------------------------------------
1 | {
2 | "exe": "ga10",
3 | "key": "private.pem",
4 | "debug": true,
5 | "heapSize": 512,
6 | "executableHeap": false,
7 | "productID": 1,
8 | "securityVersion": 1,
9 | "mounts": null,
10 | "env": null,
11 | "files": null
12 | }
--------------------------------------------------------------------------------
/ga10/go.mod:
--------------------------------------------------------------------------------
1 | module a10
2 |
3 | go 1.20
4 |
5 | require (
6 | github.com/eclipse/paho.mqtt.golang v1.4.3
7 | github.com/google/uuid v1.5.0
8 | github.com/labstack/echo/v4 v4.11.4
9 | github.com/racingmars/go3270 v0.0.0-20231111230320-21f273b327b8
10 | go.mongodb.org/mongo-driver v1.13.1
11 | golang.org/x/exp v0.0.0-20240119083558-1b970713d09a
12 | gopkg.in/yaml.v3 v3.0.1
13 | )
14 |
15 | require github.com/miekg/pkcs11 v1.1.1
16 |
17 | require gopkg.in/square/go-jose.v2 v2.6.0 // indirect
18 |
19 | require (
20 | github.com/edgelesssys/ego v1.4.1
21 | github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
22 | github.com/golang/snappy v0.0.4 // indirect
23 | github.com/google/go-tpm v0.9.0
24 | github.com/gorilla/websocket v1.5.1 // indirect
25 | github.com/klauspost/compress v1.17.4 // indirect
26 | github.com/labstack/gommon v0.4.2 // indirect
27 | github.com/mattn/go-colorable v0.1.13 // indirect
28 | github.com/mattn/go-isatty v0.0.20 // indirect
29 | github.com/montanaflynn/stats v0.7.1 // indirect
30 | github.com/valyala/bytebufferpool v1.0.0 // indirect
31 | github.com/valyala/fasttemplate v1.2.2 // indirect
32 | github.com/xdg-go/pbkdf2 v1.0.0 // indirect
33 | github.com/xdg-go/scram v1.1.2 // indirect
34 | github.com/xdg-go/stringprep v1.0.4 // indirect
35 | github.com/youmark/pkcs8 v0.0.0-20201027041543-1326539a0a0a // indirect
36 | golang.org/x/crypto v0.18.0 // indirect
37 | golang.org/x/net v0.20.0 // indirect
38 | golang.org/x/sync v0.6.0 // indirect
39 | golang.org/x/sys v0.16.0 // indirect
40 | golang.org/x/text v0.14.0 // indirect
41 | golang.org/x/time v0.5.0 // indirect
42 | )
43 |
--------------------------------------------------------------------------------
/ga10/logging/logging.go:
--------------------------------------------------------------------------------
1 | package logging
2 |
3 | import(
4 | "log"
5 | "fmt"
6 | "context"
7 | "sync"
8 | "os"
9 |
10 | "a10/utilities"
11 | "a10/datalayer"
12 | "a10/structures"
13 | "a10/configuration"
14 | )
15 |
16 |
17 | func MakeLogEntry(ch string, op string, itemid string, itemtype string, message string){
18 |
19 | logentry := structures.LogEntry{ utilities.MakeID(), utilities.MakeTimestamp(), ch, op, itemid, itemtype, message, []byte{} }
20 |
21 | if digest,err := utilities.MakeSHA256(logentry); err != nil {
22 | log.Printf("WARNING: Encoding log entry failed with %w. Entry not made.",err)
23 | } else {
24 | logentry.Hash = digest
25 |
26 | // these can be run in parallel. We don't care about return results
27 | var wg sync.WaitGroup
28 |
29 | wg.Add(3)
30 |
31 | go writeToDB(&wg,logentry)
32 | go writeToMessaging(&wg,logentry)
33 | go writeToLogfile(&wg,logentry)
34 |
35 | wg.Wait()
36 | }
37 |
38 | }
39 |
40 |
41 | func writeToDB(wgrp *sync.WaitGroup, l structures.LogEntry){
42 | _,_ = datalayer.DB.Collection("log").InsertOne(context.TODO(), l)
43 |
44 | wgrp.Done()
45 | }
46 |
47 |
48 | func writeToMessaging(wgrp *sync.WaitGroup, l structures.LogEntry){
49 | ch := fmt.Sprintf("AS/%s",l.Channel)
50 | _ = datalayer.MESSAGING.Publish(ch,0,false,makeCSVText(l))
51 |
52 | wgrp.Done()
53 | }
54 |
55 |
56 | func writeToLogfile(wgrp *sync.WaitGroup, l structures.LogEntry){
57 | f,err := os.OpenFile(configuration.ConfigData.Logging.LogFileLocation,
58 | os.O_APPEND|os.O_CREATE|os.O_WRONLY, 0644)
59 | if err != nil {
60 | log.Println("Error opening log file ",configuration.ConfigData.Logging.LogFileLocation)
61 | }
62 | defer f.Close()
63 |
64 | if _, err := f.WriteString(makeCSVText(l)); err != nil {
65 | log.Println("Error writring to log file ",configuration.ConfigData.Logging.LogFileLocation)
66 | }
67 |
68 | wgrp.Done()
69 | }
70 |
71 |
72 | func makeCSVText(l structures.LogEntry) string {
73 | return fmt.Sprintf("%s,%v,%s,%s,%s,%s,%q\n",l.ItemID, l.Timestamp, l.Channel, l.Operation, l.RefID, l.RefType, l.Message)
74 | }
--------------------------------------------------------------------------------
/ga10/operations/attestation.go:
--------------------------------------------------------------------------------
1 | package operations
2 |
3 | import(
4 | "fmt"
5 |
6 | "a10/structures"
7 | "a10/utilities"
8 | )
9 |
10 | type hashablePartClaim struct {
11 | BodyType string
12 | Header structures.ClaimHeader
13 | Body map[string]interface{}
14 | }
15 |
16 |
17 |
18 | //This function calls the attestation mechanism that eventually calls the TA on some client
19 | // ItemIDs for Element, Policy and String are provided in eid, pid and sid
20 | // A map of additional parameters in aps
21 | func Attest(element structures.Element, policy structures.Policy, session structures.Session, aps map[string]interface{}) (string, error) {
22 |
23 | var body map[string]interface{} = make(map[string]interface{})
24 |
25 | /* 1. create a protocol object
26 | 2. set the timer start
27 | 3. dispatch control over to the protocol object
28 | 4. stop timer
29 | 5. create claim
30 | 6. store claim
31 | 7. add claim to the session
32 | 8. return
33 | */
34 |
35 | // Step 1 ******************************************************
36 |
37 | protocol := element.Protocol
38 | protocolObject,_ := GetProtocol(protocol)
39 |
40 | // TODO: Need to check that the protocol exists here otherwise the acall below fails with a panic
41 |
42 | // Step 2 ******************************************************
43 |
44 | claimTimerStart := utilities.MakeTimestamp()
45 |
46 | // Step 3 ******************************************************
47 |
48 | aCALL := protocolObject.CallFunction
49 | returnedBody, ips, bodytype := aCALL( element, policy, session, aps )
50 |
51 | if bodytype == "*ERROR" {
52 | body["ERROR"] = returnedBody
53 | } else {
54 | body = returnedBody
55 | }
56 |
57 | // Step 4 ******************************************************
58 |
59 | claimTimerFinish := utilities.MakeTimestamp()
60 |
61 | // Step 5 ******************************************************
62 | // NB: we have body and bodytype from above
63 |
64 | timing := structures.Timing{ claimTimerStart, claimTimerFinish }
65 | header := structures.ClaimHeader{element, policy, session, timing, aps, ips}
66 | footer,_ := hashAndSignClaim(hashablePartClaim{ bodytype, header, body })
67 |
68 | c := structures.Claim{ "", bodytype, header, body, footer }
69 |
70 | // Step 6
71 | sid := session.ItemID
72 |
73 | cid,err := AddClaim( c ) // cid a string with the claim ID
74 | if err != nil {
75 | return "",fmt.Errorf("Error adding claim, session %v might still be open: %w",sid,err)
76 | }
77 |
78 | fmt.Printf("Added claim %v\n",cid)
79 |
80 | // if AddClaim fails, we have a bigger problem, see above note
81 | // If there is an error here, then we need a new claim type of "internal error"
82 | // but of course, if we can't add a claim then we can not add an internal error claim ---just dump something on the log!
83 | // plus specific logging to handle this - might denote on seriously fscked TA at the other end?
84 | // This is kind of the same thing that happens if there protocol object ins't found
85 |
86 | // Step 7
87 |
88 | sderr := AddClaimToSession(sid,cid)
89 | if sderr != nil {
90 | return "",fmt.Errorf("Error adding claim %v to session %v. Claim added, session may be still open: %w",cid,sid,err)
91 | }
92 |
93 | // Step 8
94 |
95 | return cid,nil
96 | }
97 |
98 |
99 |
--------------------------------------------------------------------------------
/ga10/operations/claims.go:
--------------------------------------------------------------------------------
1 | // This package contains the operations for managing elements in a system
2 | // It provides
3 | package operations
4 |
5 | import(
6 | "fmt"
7 | "context"
8 |
9 | "a10/structures"
10 | "a10/utilities"
11 | "a10/datalayer"
12 | "a10/logging"
13 |
14 | "go.mongodb.org/mongo-driver/mongo/options"
15 | "go.mongodb.org/mongo-driver/bson"
16 |
17 | )
18 |
19 | func isClaimError(c structures.Claim) bool {
20 | return c.BodyType == structures.CLAIMERROR
21 | }
22 |
23 | func CountClaims() int64 {
24 | return datalayer.Count("claims")
25 | }
26 |
27 | // AddElement is a function that takes and element structure that has a BLANK Itemid field (empty string) and stores that
28 | // element in some database
29 | // Successful storage returns the itemid for that element and a nil error.
30 | // An error is returned if an item id is given as part of the input structure.
31 | func AddClaim(e structures.Claim) (string, error) {
32 | if (e.ItemID != "") {
33 | return "", ErrorItemIDIncluded
34 | } else {
35 | e.ItemID = utilities.MakeID()
36 | _,dberr := datalayer.DB.Collection("claims").InsertOne(context.TODO(), e)
37 | logging.MakeLogEntry("C","add",e.ItemID,"claim","")
38 | return e.ItemID, dberr
39 | }
40 | }
41 |
42 |
43 | // GetElements returns a map of itemids in the ID structure. If this structure is an empty map then no elements exist in the database.
44 | func GetClaims() ([]structures.ID, error) {
45 | var claims []structures.ID
46 |
47 | filter := bson.D{ {} } // Get all
48 | options := options.Find().SetProjection(bson.D{{"itemid",1}})
49 | dbcursor,_ := datalayer.DB.Collection("claims").Find(context.TODO(), filter,options)
50 | dbcursorerror := dbcursor.All(context.TODO(),&claims)
51 |
52 | return claims, dbcursorerror
53 | }
54 |
55 | func GetClaimsAll() ([]structures.Claim, error) {
56 | var claims []structures.Claim
57 |
58 | filter := bson.D{ {} } // Get all
59 | options := options.Find().SetSort(bson.D{{"header.timing.requested",-1}})
60 |
61 | dbcursor,_ := datalayer.DB.Collection("claims").Find(context.TODO(), filter, options)
62 | dbcursorerror := dbcursor.All(context.TODO(),&claims)
63 |
64 | fmt.Printf("\n********\nClaims\n error %w \n claims %v \n*** \n",claims,dbcursorerror)
65 |
66 | return claims, dbcursorerror
67 | }
68 |
69 | func GetClaimsByElementID(eid string, maximumAmount int64) ([]structures.Claim, error) {
70 | var claims []structures.Claim
71 |
72 | if maximumAmount<1 {
73 | return claims, fmt.Errorf("Maximum amount must be a positive number")
74 | }
75 |
76 | fmt.Println("Getting for claim by element eid = %v\n",eid)
77 | filter := bson.D{ {"header.element.itemid",eid } } // TODO search for itemIDs only
78 | options := options.Find().SetSort(bson.D{{"header.timing.requested",-1}}).SetLimit(maximumAmount)
79 | dbcursor,_ := datalayer.DB.Collection("claims").Find(context.TODO(), filter, options)
80 | dbcursorerror := dbcursor.All(context.TODO(),&claims)
81 |
82 | return claims, dbcursorerror
83 | }
84 |
85 |
86 | // GetElementByItemID returns a single element or error
87 | func GetClaimByItemID(itemid string) (structures.Claim, error) {
88 | var claim structures.Claim
89 |
90 | // discard the cursor, it will be an empty entry if nothing exists
91 | filter := bson.D{ {"itemid", itemid} }
92 | dbcursorerror := datalayer.DB.Collection("claims").FindOne(context.TODO(), filter).Decode(&claim)
93 |
94 | if claim.ItemID == "" {
95 | return structures.Claim{}, ErrorItemNotFound
96 | } else {
97 | return claim, dbcursorerror
98 | }
99 | }
100 |
101 |
--------------------------------------------------------------------------------
/ga10/operations/log.go:
--------------------------------------------------------------------------------
1 | package operations
2 |
3 | import(
4 | "context"
5 | "fmt"
6 |
7 | "a10/structures"
8 | "a10/datalayer"
9 | "a10/utilities"
10 |
11 | "go.mongodb.org/mongo-driver/mongo/options"
12 | "go.mongodb.org/mongo-driver/bson"
13 |
14 | )
15 |
16 | func CountLogEntries() int64 {
17 | return datalayer.Count("log")
18 | }
19 |
20 | func GetLogEntries(maximumAmount int64) ([]structures.LogEntry,error) {
21 | var logentries []structures.LogEntry
22 |
23 | filter := bson.D{ {} } // Get all
24 |
25 | options := options.Find().SetSort(bson.D{{"timestamp",-1}}).SetLimit(maximumAmount)
26 | dbcursor,_ := datalayer.DB.Collection("log").Find(context.TODO(), filter, options)
27 | dbcursorerror := dbcursor.All(context.TODO(),&logentries)
28 |
29 | return logentries, dbcursorerror
30 | }
31 |
32 | func GetLogEntriesSince(duration string) ([]structures.LogEntry,error) {
33 | var logentries []structures.LogEntry
34 |
35 | ts := utilities.TimeStampHoursAgo(duration)
36 | fmt.Printf("Duration is %v, ts is %v\n",duration,ts)
37 |
38 | filter := bson.D{{"timestamp", bson.D{{"$gt",ts}}}} // Get all since given point in time
39 |
40 | options := options.Find().SetSort(bson.D{{"timestamp",-1}})
41 |
42 | dbcursor,_ := datalayer.DB.Collection("log").Find(context.TODO(), filter, options)
43 | dbcursorerror := dbcursor.All(context.TODO(),&logentries)
44 |
45 | return logentries, dbcursorerror
46 | }
47 |
--------------------------------------------------------------------------------
/ga10/operations/opaqueobjects.go:
--------------------------------------------------------------------------------
1 | // This package contains the operations for managing elements in a system
2 | // It provides
3 | package operations
4 |
5 | import(
6 | "fmt"
7 | "context"
8 |
9 | "a10/structures"
10 | "a10/datalayer"
11 | "a10/logging"
12 |
13 | "go.mongodb.org/mongo-driver/mongo/options"
14 | "go.mongodb.org/mongo-driver/bson"
15 |
16 | )
17 |
18 | func CountOpaqueOjects() int64 {
19 | return datalayer.Count("hashes")
20 | }
21 |
22 | func AddOpaqueObject(h structures.OpaqueObject) (string, error) {
23 | options := options.Update().SetUpsert(true)
24 | filter := bson.D{{"value",h.Value}}
25 | //update := bson.D{{ "$set", bson.D{{ h }}}}
26 | _,dberr := datalayer.DB.Collection("opaqueobjects").UpdateOne(context.TODO(), filter, h, options)
27 | msg := fmt.Sprintf("%s,%s",h.Type,h.ShortDescription)
28 | logging.MakeLogEntry("IM","add",h.Value,"object",msg)
29 | return h.Value, dberr
30 |
31 | }
32 |
33 | func UpdateOpaqueObject(replacement structures.OpaqueObject) (string, error) {
34 | return AddOpaqueObject(replacement)
35 | }
36 |
37 | func DeleteOpaqueObject(v string) error {
38 | filter := bson.D{{"value",v}}
39 | deleteresult, err := datalayer.DB.Collection("opaqueobjects").DeleteOne(context.TODO(), filter)
40 |
41 | if err != nil {
42 | return err
43 | } else if deleteresult.DeletedCount != 1 {
44 | return ErrorItemNotDeleted
45 | } else {
46 | logging.MakeLogEntry("IM","delete",v,"object","")
47 | return nil
48 | }
49 | }
50 |
51 |
52 | func GetOpaqueObjects() ([]structures.OpaqueObject, error) {
53 | var elems []structures.OpaqueObject
54 |
55 | filter := bson.D{ {} } // Get all
56 | dbcursor,_ := datalayer.DB.Collection("opaqueobjects").Find(context.TODO(), filter)
57 | dbcursorerror := dbcursor.All(context.TODO(),&elems)
58 |
59 | return elems, dbcursorerror
60 | }
61 |
62 |
63 |
64 | // GetElementByItemID returns a single element or error
65 | func GetOpaqueObjectByValue(v string) (structures.OpaqueObject, error) {
66 | var elem structures.OpaqueObject
67 |
68 | // discard the cursor, it will be an empty entry if nothing exists
69 | filter := bson.D{ {"value", v} }
70 | dbcursorerror := datalayer.DB.Collection("opaqueobjects").FindOne(context.TODO(), filter).Decode(&elem)
71 |
72 | if elem.Value == "" {
73 | return structures.OpaqueObject{}, ErrorItemNotFound
74 | } else {
75 | return elem, dbcursorerror
76 | }
77 | }
78 |
--------------------------------------------------------------------------------
/ga10/operations/operrors.go:
--------------------------------------------------------------------------------
1 | package operations
2 |
3 | import(
4 | "errors"
5 | )
6 |
7 | var (
8 | ErrorItemIDIncluded = errors.New("ItemID included")
9 | ErrorDatabaseError = errors.New("Database Error")
10 |
11 | ErrorItemNotUpdated = errors.New("Item not updated")
12 | ErrorItemNotFound = errors.New("Item not found")
13 | ErrorItemNotDeleted = errors.New("Element not deleted")
14 |
15 |
16 | )
--------------------------------------------------------------------------------
/ga10/operations/protocols.go:
--------------------------------------------------------------------------------
1 | package operations
2 |
3 | import(
4 | "fmt"
5 | "golang.org/x/exp/maps"
6 |
7 | "a10/structures"
8 | "a10/datalayer"
9 | "a10/logging"
10 | )
11 |
12 | func CountProtocols() int64 {
13 | return datalayer.Count("protocols")
14 | }
15 |
16 | // GetElements returns a map of itemids in the ID structure. If this structure is an empty map then no elements exist in the database.
17 | func GetProtocols() []structures.Protocol {
18 | return maps.Values(datalayer.ProtocolsDatabase)
19 | }
20 |
21 | func GetProtocol(n string) (structures.Protocol, error) {
22 | r,exists := datalayer.ProtocolsDatabase[n]
23 |
24 | if (exists) {
25 | return r,nil
26 | } else {
27 | return r,fmt.Errorf("No such protocol")
28 | }
29 | }
30 |
31 | func AddProtocol(p structures.Protocol) {
32 | k := p.Name
33 | datalayer.ProtocolsDatabase[k] = p
34 | logging.MakeLogEntry("IM","add","","protocol",k)
35 | }
--------------------------------------------------------------------------------
/ga10/operations/results.go:
--------------------------------------------------------------------------------
1 | // This package contains the operations for managing elements in a system
2 | // It provides
3 | package operations
4 |
5 | import(
6 | "fmt"
7 | "context"
8 |
9 | "a10/structures"
10 | "a10/utilities"
11 | "a10/datalayer"
12 | "a10/logging"
13 |
14 | "go.mongodb.org/mongo-driver/mongo/options"
15 | "go.mongodb.org/mongo-driver/bson"
16 |
17 | )
18 |
19 | func CountResults() int64 {
20 | return datalayer.Count("results")
21 | }
22 |
23 | // AddElement is a function that takes and element structure that has a BLANK Itemid field (empty string) and stores that
24 | // element in some database
25 | // Successful storage returns the itemid for that element and a nil error.
26 | // An error is returned if an item id is given as part of the input structure.
27 | func AddResult(e structures.Result) (string, error) {
28 | if (e.ItemID != "") {
29 | return "", ErrorItemIDIncluded
30 | } else {
31 | e.ItemID = utilities.MakeID()
32 | _,dberr := datalayer.DB.Collection("results").InsertOne(context.TODO(), e)
33 | logging.MakeLogEntry("R","add",e.ItemID,"result",fmt.Sprintf("%v",e.Result) )
34 | return e.ItemID, dberr
35 | }
36 | }
37 |
38 |
39 | // GetElements returns a map of itemids in the ID structure. If this structure is an empty map then no elements exist in the database.
40 | func GetResults() ([]structures.ID, error) {
41 | var results []structures.ID
42 |
43 | filter := bson.D{ {} } // Get all
44 | options := options.Find().SetProjection(bson.D{{"itemid",1}})
45 | dbcursor,_ := datalayer.DB.Collection("results").Find(context.TODO(), filter,options)
46 | dbcursorerror := dbcursor.All(context.TODO(),&results)
47 |
48 | return results, dbcursorerror
49 | }
50 |
51 |
52 | func GetResultsAll() ([]structures.Result, error) {
53 | var results []structures.Result
54 |
55 | filter := bson.D{ {} } // Get all
56 | options := options.Find().SetSort(bson.D{{"verifiedat",-1}})
57 | dbcursor,_ := datalayer.DB.Collection("results").Find(context.TODO(), filter, options)
58 | dbcursorerror := dbcursor.All(context.TODO(),&results)
59 |
60 | return results, dbcursorerror
61 | }
62 |
63 |
64 | func GetResultsByElementID(eid string, maximumAmount int64) ([]structures.Result, error) {
65 | var Results []structures.Result
66 |
67 | fmt.Printf("getting results for %v\n",eid)
68 |
69 | filter := bson.D{ { "elementid",eid } } // Get all // TODO search for itemIDs only
70 | options := options.Find().SetSort(bson.D{{"verifiedAt",-1}}).SetLimit(maximumAmount)
71 | dbcursor,_ := datalayer.DB.Collection("results").Find(context.TODO(), filter, options)
72 | dbcursorerror := dbcursor.All(context.TODO(),&Results)
73 |
74 | return Results, dbcursorerror
75 | }
76 |
77 |
78 | // GetElementByItemID returns a single element or error
79 | func GetResultByItemID(itemid string) (structures.Result, error) {
80 | var Result structures.Result
81 |
82 | // discard the cursor, it will be an empty entry if nothing exists
83 | filter := bson.D{ {"itemid", itemid} }
84 | dbcursorerror := datalayer.DB.Collection("results").FindOne(context.TODO(), filter).Decode(&Result)
85 |
86 | if Result.ItemID == "" {
87 | return structures.Result{}, ErrorItemNotFound
88 | } else {
89 | return Result, dbcursorerror
90 | }
91 | }
92 |
93 |
--------------------------------------------------------------------------------
/ga10/operations/rules.go:
--------------------------------------------------------------------------------
1 | package operations
2 |
3 | import(
4 | "errors"
5 | "sort"
6 | "golang.org/x/exp/maps"
7 |
8 | "a10/structures"
9 | "a10/datalayer"
10 | "a10/logging"
11 | )
12 |
13 | func CountRules() int64 {
14 | return datalayer.Count("rules")
15 | }
16 |
17 | // GetElements returns a map of itemids in the ID structure. If this structure is an empty map then no elements exist in the database.
18 | func GetRules() []structures.Rule {
19 | keys := maps.Keys(datalayer.RulesDatabase)
20 | sort.Strings(keys)
21 |
22 | vals := make([]structures.Rule, 0) // empty
23 | for _,k := range keys {
24 | vals = append(vals,datalayer.RulesDatabase[k])
25 | }
26 | return vals
27 |
28 | }
29 |
30 | func GetRule(n string) (structures.Rule, error) {
31 | r,exists := datalayer.RulesDatabase[n]
32 |
33 | if (exists) {
34 | return r,nil
35 | } else {
36 | return r,errors.New("No such rule")
37 | }
38 | }
39 |
40 | func AddRule(r structures.Rule) {
41 | k := r.Name
42 | datalayer.RulesDatabase[k] = r
43 | logging.MakeLogEntry("IM","add","","rule",k)
44 | }
--------------------------------------------------------------------------------
/ga10/operations/signingFunctions.go:
--------------------------------------------------------------------------------
1 | package operations
2 |
3 | import(
4 | "fmt"
5 |
6 | "crypto"
7 | "crypto/rsa"
8 | "crypto/rand"
9 |
10 | "a10/structures"
11 | "a10/utilities"
12 | )
13 |
14 | var publickey *rsa.PublicKey
15 | var privatekey *rsa.PrivateKey
16 |
17 | func init() {
18 | fmt.Printf("generating private, public key pair for claim signing - just for this session so no chance to verify later. THese keys MUST be external\n")
19 |
20 | privatekey,_ = rsa.GenerateKey(rand.Reader, 2048)
21 | publickey = &privatekey.PublicKey
22 | }
23 |
24 |
25 |
26 | func hashAndSignClaim(h hashablePartClaim) (structures.ClaimFooter,error) {
27 | digest,err := utilities.MakeSHA256(h)
28 | if err != nil {
29 | return structures.ClaimFooter{ []byte{}, []byte{} }, fmt.Errorf("hashAndSignfailed with %v",err)
30 | }
31 |
32 | signature, _ := rsa.SignPSS(rand.Reader, privatekey, crypto.SHA256, digest, nil)
33 |
34 | err = rsa.VerifyPSS(publickey, crypto.SHA256, digest, signature, nil)
35 | if err!=nil {
36 | return structures.ClaimFooter{ []byte{}, []byte{} }, fmt.Errorf("Verification of hashAndSignfailed with %v",err)
37 | }
38 |
39 | return structures.ClaimFooter{ digest, signature }, nil
40 | }
41 |
42 |
43 |
44 |
45 |
46 | func hashAndSignResult(h hashablePartResult) (structures.ResultFooter,error) {
47 | digest,err := utilities.MakeSHA256(h)
48 | if err != nil {
49 | return structures.ResultFooter{ []byte{}, []byte{} }, fmt.Errorf("hashAndSignfailed with %v",err)
50 | }
51 |
52 | signature, _ := rsa.SignPSS(rand.Reader, privatekey, crypto.SHA256, digest, nil)
53 |
54 | err = rsa.VerifyPSS(publickey, crypto.SHA256, digest, signature, nil)
55 | if err!=nil {
56 | return structures.ResultFooter{ []byte{}, []byte{} }, fmt.Errorf("Verification of hashAndSignfailed with %v",err)
57 | }
58 |
59 | return structures.ResultFooter{ digest, signature }, nil
60 | }
61 |
62 |
63 |
64 |
65 | func hashAndSignSession(h hashablePartSession) (structures.SessionFooter,error) {
66 | digest,err := utilities.MakeSHA256(h)
67 | if err != nil {
68 | return structures.SessionFooter{ []byte{}, []byte{} }, fmt.Errorf("hashAndSignfailed with %v",err)
69 | }
70 |
71 | signature, _ := rsa.SignPSS(rand.Reader, privatekey, crypto.SHA256, digest, nil)
72 |
73 | err = rsa.VerifyPSS(publickey, crypto.SHA256, digest, signature, nil)
74 | if err!=nil {
75 | return structures.SessionFooter{ []byte{}, []byte{} }, fmt.Errorf("Verification of hashAndSignfailed with %v",err)
76 | }
77 |
78 | return structures.SessionFooter{ digest, signature }, nil
79 | }
--------------------------------------------------------------------------------
/ga10/otherconfigfiles/local.yaml:
--------------------------------------------------------------------------------
1 | #Some general naming
2 | system:
3 | name: ASVR_GO_1
4 |
5 | #MongoDB Configuration
6 | database:
7 | connection: mongodb://127.0.0.1:27017
8 | name: localasvr
9 |
10 | #MQTT Configuration
11 | messaging:
12 | broker: 127.0.0.1
13 | port: 1883
14 | clientid: ASVR_GO_1_LOCAL
15 |
16 | #REST Interface Configuration
17 | rest:
18 | port: 8520
19 | crt: temporary.crt
20 | key: temporary.key
21 | usehttp: true
22 |
23 | #Web Interface Configuration
24 | web:
25 | port: 8540
26 | crt: temporary.crt
27 | key: temporary.key
28 | usehttp: true
29 |
30 | #Log file
31 | logfile:
32 | location: /tmp/ga10.log
33 |
--------------------------------------------------------------------------------
/ga10/otherconfigfiles/nconfig.yaml:
--------------------------------------------------------------------------------
1 | #Some general naming
2 | system:
3 | name: ASVR_GO_1
4 |
5 | #MongoDB Configuration
6 | database:
7 | connection: mongodb://10.144.176.154:27017
8 | name: attestation2
9 |
10 | #MQTT Configuration
11 | messaging:
12 | broker: 10.144.176.154
13 | port: 1883
14 | clientid: ASVR_GO_1
15 |
16 | #REST Interface Configuration
17 | rest:
18 | port: 8520
19 | crt: temporary.crt
20 | key: temporary.key
21 | usehttp: true
22 |
23 | #Web Interface Configuration
24 | web:
25 | port: 8540
26 | crt: temporary.crt
27 | key: temporary.key
28 | usehttp: true
29 |
30 | #Log file
31 | logfile:
32 | location: /tmp/ga10.log
33 |
--------------------------------------------------------------------------------
/ga10/protocols/netconfprotocol/public.go:
--------------------------------------------------------------------------------
1 | package netconfprotocol
2 |
3 | import(
4 | "fmt"
5 | "log"
6 | "crypto/rand"
7 |
8 | "a10/structures"
9 | )
10 |
11 | const nonceSize int = 32
12 |
13 | func Registration() (structures.Protocol) {
14 | intents := []string{"null/good","null/test"}
15 |
16 | return structures.Protocol{"A10NETCONF","POC protocol module for NetConf",Call, intents}
17 | }
18 |
19 | func Call(e structures.Element, p structures.Policy, s structures.Session, cps map[string]interface{}) (map[string]interface{}, map[string]interface{},string) {
20 |
21 | // Create a test body
22 |
23 | rtn := map[string]interface{}{
24 | "foo":"bar",
25 | "calling": fmt.Sprintf("with protocol %v I would send an intent to %v",e.Protocol,p.Intent),
26 | "aNumber": 42,
27 | }
28 |
29 | nce := make([]byte, nonceSize)
30 | _, _ = rand.Read(nce)
31 |
32 | ips := map[string]interface{}{
33 | "nonce":nce,
34 | }
35 |
36 | // Check if the policy intent was null/null, if so then return with the bodytype being set to null/test
37 | // or error if the above is false.
38 | //
39 | // Claim bodytype should be set to error and a ClaimError structure returned in an error field
40 |
41 | if p.Intent=="null/null" {
42 | log.Println(" null call worked ")
43 | rtn["worked"] = true
44 | return rtn,ips,"null/test"
45 | } else {
46 | log.Println(" null call bad error ")
47 | rtn["error"] = "Error here"
48 | return rtn,ips,structures.CLAIMERROR
49 | }
50 | }
--------------------------------------------------------------------------------
/ga10/protocols/nullprotocol/public.go:
--------------------------------------------------------------------------------
1 | package nullprotocol
2 |
3 | import(
4 | "fmt"
5 | "log"
6 | "crypto/rand"
7 |
8 | "a10/structures"
9 | )
10 |
11 | const nonceSize int = 32
12 |
13 | func Registration() (structures.Protocol) {
14 | intents := []string{"*/*"}
15 |
16 | return structures.Protocol{"A10NULLPROTOCOL","Testing protocol, always returns a test claim",Call, intents}
17 | }
18 |
19 | func Call(e structures.Element, p structures.Policy, s structures.Session, cps map[string]interface{}) (map[string]interface{}, map[string]interface{}, string) {
20 |
21 | // Create a test body
22 |
23 | rtn := map[string]interface{}{
24 | "foo":"bar",
25 | "calling": fmt.Sprintf("with protocol %v I would send an intent to %v",e.Protocol,p.Intent),
26 | "aNumber": 42,
27 | }
28 |
29 | nce := make([]byte, nonceSize)
30 | _, _ = rand.Read(nce)
31 |
32 | ips := map[string]interface{}{
33 | "nonce":nce,
34 | }
35 |
36 | // Check if the policy intent was null/null, if so then return with the bodytype being set to null/test
37 | // or error if the above is false.
38 | //
39 | // Claim bodytype should be set to error and a ClaimError structure returned in an error field
40 |
41 | if p.Intent=="null/null" {
42 | log.Println(" null call worked ")
43 | rtn["worked"] = true
44 | return rtn,ips,"null/test"
45 | } else {
46 | log.Println(" null call bad error ")
47 | rtn["error"] = "Error here"
48 | return rtn,ips,structures.CLAIMERROR
49 | }
50 | }
--------------------------------------------------------------------------------
/ga10/protocols/registerProtocols.go:
--------------------------------------------------------------------------------
1 | package protocols
2 |
3 | import (
4 | "a10/operations"
5 |
6 | "a10/protocols/a10httprestv2"
7 | "a10/protocols/marblerun"
8 | "a10/protocols/netconfprotocol"
9 | "a10/protocols/nullprotocol"
10 | "a10/protocols/testcontainerprotocol"
11 | )
12 |
13 | func RegisterProtocols() {
14 | operations.AddProtocol(a10httprestv2.Registration())
15 | operations.AddProtocol(nullprotocol.Registration())
16 | operations.AddProtocol(netconfprotocol.Registration())
17 | operations.AddProtocol(marblerun.Registration())
18 | operations.AddProtocol(testcontainerprotocol.Registration())
19 | }
20 |
--------------------------------------------------------------------------------
/ga10/protocols/testcontainerprotocol/public.go:
--------------------------------------------------------------------------------
1 | package testcontainerprotocol
2 |
3 | import(
4 | "fmt"
5 | "crypto/rand"
6 |
7 | "a10/structures"
8 | )
9 |
10 | const nonceSize int = 32
11 |
12 | func Registration() (structures.Protocol) {
13 | intents := []string{"testcontainers/repoimageintegrity"}
14 |
15 | return structures.Protocol{"TESTCONTAINERPROTOCOL","Test protocol for containers",Call, intents}
16 | }
17 |
18 | func Call(e structures.Element, p structures.Policy, s structures.Session, cps map[string]interface{}) (map[string]interface{}, map[string]interface{}, string) {
19 |
20 | // Create a test body
21 |
22 | // create a nonce, because why not?
23 |
24 | nce := make([]byte, nonceSize)
25 | _, _ = rand.Read(nce)
26 |
27 | // add it to the set of parameters supplied to this function
28 |
29 | ips := map[string]interface{}{
30 | "nonce":nce,
31 | }
32 |
33 | // **************************************
34 | // When calling the real "trust agent" endpoint, ips would be passed as the parameters to whatever function is called that supports the intent
35 | // This is where the call code goes
36 | // **************************************
37 |
38 | // return the body - we create a test body here
39 |
40 | rtn := map[string]interface{}{
41 | "foo":"bar",
42 | "calling": fmt.Sprintf("with protocol %v I would send an intent to %v",e.Protocol,p.Intent),
43 | "aNumber": 42,
44 | }
45 |
46 | // Note, if anything above fails please return an error quote, ie the final string in the return below would be *ERROR
47 |
48 | // rtn is the return body
49 | // ips is the generated parameters, ie: cps + anything else
50 | // stirng contains the type of the result. If this is *ERROR then the claim is an error claim - any later verification over that structure would fail accordingly
51 |
52 | return rtn,ips,"testcontainers/repoimageintegrity"
53 |
54 | }
--------------------------------------------------------------------------------
/ga10/rules/nullrule/public.go:
--------------------------------------------------------------------------------
1 | package nullrule
2 |
3 | import(
4 | "a10/structures"
5 | )
6 |
7 |
8 | func Registration() []structures.Rule {
9 |
10 | ruleS := structures.Rule{ "null_success","A rule that always returns success", CallruleS, false}
11 | ruleF := structures.Rule{ "null_fail","A rule that always returns fail", CallruleF, false}
12 |
13 | ruleV := structures.Rule{ "null_verifycallfail","A rule that always returns verifycallfail error", CallruleV, false}
14 | ruleN := structures.Rule{ "null_noresult","A rule that always returns noresult error", CallruleN, false}
15 | ruleE := structures.Rule{ "null_verifycallerrorattempt","A rule that always returns verifycallerrorattempt error", CallruleE, false}
16 |
17 | ruleMEV := structures.Rule{ "null_missingEV","A rule that always returns missing expected value error", CallruleMEV, false}
18 | ruleRCF := structures.Rule{ "null_rulecallfailure","A rule that always returns rule call failure error", CallruleRCF, false}
19 | ruleU := structures.Rule{ "null_unsetresultvalue","A rule that always returns unste result value error", CallruleU, false}
20 |
21 |
22 | return []structures.Rule{ ruleS, ruleF, ruleV, ruleN, ruleE, ruleMEV, ruleRCF, ruleU }
23 | }
24 |
25 | func CallruleS(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) {
26 | return structures.Success,"This a demonstration of a success result",nil
27 | }
28 |
29 | func CallruleF(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) {
30 | return structures.Fail,"This a demonstration of a fail result",nil
31 | }
32 |
33 | func CallruleE(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) {
34 | return structures.VerifyClaimErrorAttempt,"This a demonstration of verifycallerrorattempt",nil
35 | }
36 |
37 | func CallruleV(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) {
38 | return structures.VerifyCallFailure,"This a demonstration of a verify call fail result",nil
39 | }
40 |
41 | func CallruleN(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) {
42 | return structures.NoResult,"This a demonstration of no result",nil
43 | }
44 |
45 |
46 |
47 | func CallruleMEV(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) {
48 | return structures.MissingExpectedValue,"This a demonstration of missing expected value",nil
49 | }
50 | func CallruleRCF(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) {
51 | return structures.RuleCallFailure,"This a demonstration of rule call failure",nil
52 | }
53 | func CallruleU(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) {
54 | return structures.UnsetResultValue,"This a demonstration of unset result value",nil
55 | }
56 |
57 |
58 |
--------------------------------------------------------------------------------
/ga10/rules/registerRules.go:
--------------------------------------------------------------------------------
1 | package rules
2 |
3 | import (
4 | "a10/operations"
5 | "a10/structures"
6 |
7 | "a10/rules/keylime"
8 | "a10/rules/marblerun"
9 | "a10/rules/nullrule"
10 | "a10/rules/sysrules"
11 | "a10/rules/tpm2rules"
12 |
13 | "a10/rules/testcontainerrules"
14 | )
15 |
16 | func RegisterRules() {
17 | registerListOfRules(nullrule.Registration())
18 | registerListOfRules(tpm2rules.Registration())
19 | registerListOfRules(marblerun.Registration())
20 | registerListOfRules(testcontainerrules.Registration())
21 | registerListOfRules(sysrules.Registration())
22 | registerListOfRules(keylime.Registration())
23 | }
24 |
25 | func registerListOfRules(rs []structures.Rule) {
26 | for _, r := range rs {
27 | operations.AddRule(r)
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/ga10/rules/sysrules/public.go:
--------------------------------------------------------------------------------
1 | package sysrules
2 |
3 | import(
4 | "a10/structures"
5 | )
6 |
7 |
8 | func Registration() []structures.Rule {
9 |
10 | ruleS := structures.Rule{ "sys_taRunningSafely","Checks the the TA is NOT in unsafe mode of operation", Callrulesafe, false}
11 |
12 |
13 | return []structures.Rule{ ruleS }
14 | }
15 |
16 | func Callrulesafe(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) {
17 |
18 | unsafevalue, ok := claim.Body["unsafe"]
19 | if !ok {
20 | return structures.RuleCallFailure, "TA not of correct type, or not reporting unsafe parameter value", nil
21 | }
22 |
23 | if unsafevalue == true {
24 | return structures.Fail, "TA operating in UNSAFE mode", nil
25 | } else {
26 | return structures.Success, "TA operating in safe mode", nil
27 | }
28 | }
29 |
--------------------------------------------------------------------------------
/ga10/rules/testcontainerrules/public.go:
--------------------------------------------------------------------------------
1 | package testcontainerrules
2 |
3 | import(
4 | "a10/structures"
5 | "fmt"
6 | "reflect"
7 | )
8 |
9 |
10 | func Registration() []structures.Rule {
11 |
12 | ruleN := structures.Rule{ "testcontainer_LIFE","The rule returns success if the nunber is 42", CallruleN, false}
13 | ruleX := structures.Rule{ "testcontainer_43","The rule returns success if the nunber is 43 - which will not happen", CallruleX, false}
14 | ruleF := structures.Rule{ "testcontainer_FOOBAR","The rule returns success if the response to foo is bar", CallruleF, false}
15 |
16 | return []structures.Rule{ ruleN, ruleX, ruleF }
17 | }
18 |
19 | func CallruleN(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) {
20 |
21 | number, ok := (claim.Body)["aNumber"]
22 | if !ok {
23 | return structures.VerifyCallFailure, "Missing body",nil
24 | }
25 |
26 |
27 |
28 | if number==int32(42) {
29 | return structures.Success, "Now what is the question?",nil
30 | } else {
31 | return structures.Fail, "Earth 2 required",nil
32 | }
33 |
34 | }
35 |
36 |
37 |
38 | func CallruleX(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) {
39 |
40 | number, ok := (claim.Body)["aNumber"]
41 | if !ok {
42 | return structures.VerifyCallFailure, "Missing body",nil
43 | }
44 |
45 | if number==int32(43) {
46 | return structures.Success, "Correctly got the wrong answer",nil
47 | } else {
48 | return structures.Fail, "Earth 2 with more mice required",nil
49 | }
50 | }
51 |
52 |
53 |
54 | func CallruleF(claim structures.Claim, rule string, ev structures.ExpectedValue, session structures.Session, parameter map[string]interface{}) (structures.ResultValue, string, error) {
55 |
56 | foobar, ok := (claim.Body)["foo"]
57 | if !ok {
58 | return structures.VerifyCallFailure, "Missing body",nil
59 | }
60 |
61 | fmt.Printf("\n\nNumber is %v type is %v == %v %v\n\n",foobar,reflect.TypeOf(foobar), foobar=="bar",reflect.TypeOf("bar"))
62 |
63 |
64 | if foobar=="bar" {
65 | return structures.Success, "Correctly got the wrong answer",nil
66 | } else {
67 | return structures.Fail, "Earth 2 with more mice required",nil
68 | }
69 | }
70 |
--------------------------------------------------------------------------------
/ga10/services/restapi/endpointOpaqueObjects.go:
--------------------------------------------------------------------------------
1 | package restapi
2 |
3 | import(
4 | "log"
5 | "net/http"
6 |
7 | "a10/operations"
8 | "a10/structures"
9 |
10 | "github.com/labstack/echo/v4"
11 | )
12 |
13 | type returnOpaqueObjects struct {
14 | Objects []structures.OpaqueObject
15 | Length int
16 | }
17 |
18 |
19 |
20 | func getOpaqueObjects(c echo.Context) error {
21 | elems,err := operations.GetOpaqueObjects()
22 |
23 | if err != nil {
24 | log.Println("err=",err)
25 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err))
26 | } else {
27 | //Convert elems from []structures.ID into a []string
28 | var elems_str []structures.OpaqueObject
29 | for _,e := range elems {
30 | elems_str = append(elems_str,e)
31 | }
32 |
33 | //Marshall into JSON
34 | elems_struct := returnOpaqueObjects{ elems_str, len(elems_str) }
35 |
36 | return c.JSON(http.StatusOK, elems_struct)
37 | }
38 | }
39 |
40 | func getOpaqueObjectByValue(c echo.Context) error {
41 | value := c.Param("value")
42 |
43 | elem,err := operations.GetOpaqueObjectByValue(value)
44 |
45 | if err != nil {
46 | log.Println("err=",err)
47 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err))
48 | } else {
49 | return c.JSON(http.StatusOK, elem)
50 | }
51 | }
52 |
53 |
54 |
55 | type postOpaqueObjectReturn struct {
56 | Itemid string `json:"itemid"`
57 | Error string `json:"error"`
58 | }
59 |
60 |
61 |
62 | func postOpaqueObject(c echo.Context) error {
63 | elem := new(structures.OpaqueObject)
64 |
65 | if err := c.Bind(elem); err != nil {
66 | clienterr := postOpaqueObjectReturn{ "",err.Error() }
67 | return c.JSON(http.StatusBadRequest, clienterr)
68 | }
69 |
70 | res,err := operations.AddOpaqueObject(*elem)
71 |
72 | if err!=nil {
73 | response := postOpaqueObjectReturn{ res,err.Error() }
74 | return c.JSON(http.StatusInternalServerError, response)
75 | } else {
76 | response := postOpaqueObjectReturn{ res,"" }
77 | return c.JSON(http.StatusCreated, response)
78 | }
79 | }
80 |
81 |
82 | func putOpaqueObject(c echo.Context) error {
83 | return postOpaqueObject(c)
84 | }
85 |
86 |
87 |
88 | func deleteOpaqueObject(c echo.Context) error {
89 | value := c.Param("value")
90 |
91 | err := operations.DeleteOpaqueObject(value)
92 |
93 | if err != nil {
94 | response := postOpaqueObjectReturn{ value,err.Error() }
95 | return c.JSON(http.StatusInternalServerError, response)
96 | } else {
97 | err = operations.DeleteElement(value)
98 | if err != nil {
99 | response := postOpaqueObjectReturn{ value,err.Error() }
100 | return c.JSON(http.StatusInternalServerError, response)
101 | } else {
102 | response := postOpaqueObjectReturn{ value,"" }
103 | return c.JSON(http.StatusOK, response)
104 | }
105 | }
106 | }
--------------------------------------------------------------------------------
/ga10/services/restapi/endpointsAttestVerify.go:
--------------------------------------------------------------------------------
1 | package restapi
2 |
3 | import (
4 | "fmt"
5 | "net/http"
6 |
7 | "a10/operations"
8 | "a10/structures"
9 |
10 | "github.com/labstack/echo/v4"
11 | )
12 |
13 | type postAttestReturn struct {
14 | Itemid string `json:"itemid"`
15 | Error string `json:"error"`
16 | }
17 |
18 | type postVerifyReturn struct {
19 | Itemid string `json:"itemid"`
20 | Result structures.ResultValue `json:"result"`
21 | Error string `json:"error"`
22 | }
23 |
24 | type attestStr struct {
25 | EID string `json:"eid"`
26 | PID string `json:"pid"`
27 | SID string `json:"sid"`
28 | Parameters map[string]interface{} `json:"parameters",bson:"parameters"`
29 | }
30 |
31 | type verifyStr struct {
32 | CID string `json:"cid"`
33 | Rule string `json:"rule"`
34 | SID string `json:"sid"`
35 | Parameters map[string]interface{} `json:"parameters",bson:"parameters"`
36 | }
37 |
38 | func postAttest(c echo.Context) error {
39 | att := new(attestStr)
40 | if err := c.Bind(att); err != nil {
41 | clienterr := postAttestReturn{"", err.Error()}
42 | return c.JSON(http.StatusBadRequest, clienterr)
43 | }
44 |
45 | eid := (*att).EID
46 | pid := (*att).PID
47 | sid := (*att).SID
48 |
49 | element, err := operations.GetElementByItemID(eid)
50 | if err != nil {
51 | fmt.Errorf("Element not found: %v", err)
52 | }
53 |
54 | policy, err := operations.GetPolicyByItemID(pid)
55 | if err != nil {
56 | fmt.Errorf("Policy not found: %v", err)
57 | }
58 |
59 | session, err := operations.GetSessionByItemID(sid)
60 | if err != nil {
61 | fmt.Errorf("Session not found: %v", err)
62 | }
63 |
64 | res, err := operations.Attest(element, policy, session, (*att).Parameters)
65 |
66 | if err != nil {
67 | response := postAttestReturn{res, err.Error()}
68 | return c.JSON(http.StatusInternalServerError, response)
69 | } else {
70 | response := postAttestReturn{res, ""}
71 | return c.JSON(http.StatusAccepted, response)
72 | }
73 |
74 | }
75 |
76 | func postVerify(c echo.Context) error {
77 | att := new(verifyStr)
78 | if err := c.Bind(att); err != nil {
79 | clienterr := postVerifyReturn{"", structures.VerifyCallFailure, err.Error()}
80 | return c.JSON(http.StatusBadRequest, clienterr)
81 | }
82 |
83 | cid := (*att).CID
84 | r := (*att).Rule
85 | sid := (*att).SID
86 | ps := (*att).Parameters
87 |
88 | claim, err := operations.GetClaimByItemID(cid)
89 | if err != nil {
90 | return fmt.Errorf("claim not found: %v", err)
91 | }
92 |
93 | rule, err := operations.GetRule(r)
94 | if err != nil {
95 | return fmt.Errorf("rule not found: %v", rule)
96 | }
97 |
98 | session, err := operations.GetSessionByItemID(sid)
99 | if err != nil {
100 | return fmt.Errorf("session not found: %v", err)
101 | }
102 |
103 | res, rv, err := operations.Verify(claim, rule, session, ps)
104 |
105 | if err != nil {
106 | response := postVerifyReturn{res, rv, err.Error()}
107 | return c.JSON(http.StatusInternalServerError, response)
108 | } else {
109 | response := postVerifyReturn{res, rv, ""}
110 | return c.JSON(http.StatusAccepted, response)
111 | }
112 |
113 | }
114 |
--------------------------------------------------------------------------------
/ga10/services/restapi/endpointsClaims.go:
--------------------------------------------------------------------------------
1 | package restapi
2 |
3 | import(
4 | "log"
5 | "net/http"
6 | "strconv"
7 |
8 | "a10/operations"
9 | "a10/structures"
10 | )
11 |
12 | import(
13 | "github.com/labstack/echo/v4"
14 | )
15 |
16 | type returnClaims struct {
17 | Claims []string `json:"claims"`
18 | Length int `json:"length"`
19 | }
20 |
21 | func getClaims(c echo.Context) error {
22 | claims,err := operations.GetClaims()
23 |
24 | if err != nil {
25 | log.Println("err=",err)
26 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err))
27 | } else {
28 | //Convert elems from []structures.ID into a []string
29 | var claims_str []string
30 | for _,e := range claims {
31 | claims_str = append(claims_str,e.ItemID)
32 | }
33 |
34 | //Marshall into JSON
35 | claims_struct := returnClaims{ claims_str, len(claims_str) }
36 |
37 | return c.JSON(http.StatusOK, claims_struct)
38 | }
39 | }
40 |
41 | func getClaim (c echo.Context) error {
42 | itemid := c.Param("itemid")
43 | claim,err := operations.GetClaimByItemID(itemid)
44 |
45 | if err != nil {
46 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err))
47 | } else {
48 | return c.JSON(http.StatusOK, claim)
49 | }
50 | }
51 |
52 | // GetClaimsByElementID
53 | func getClaimsByElementID (c echo.Context) error {
54 | itemid := c.Param("itemid")
55 | max_query := c.QueryParam("max")
56 | max, err := strconv.ParseInt(max_query, 10, 64)
57 | if err != nil {
58 | max=200
59 | }
60 |
61 | claims,err := operations.GetClaimsByElementID(itemid, max)
62 |
63 | if err != nil {
64 | log.Println("err=",err)
65 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err))
66 | } else {
67 | //Convert elems from []structures.ID into a []string
68 | var claims_str []string
69 | for _,e := range claims {
70 | claims_str = append(claims_str,e.ItemID)
71 | }
72 |
73 | //Marshall into JSON
74 | claims_struct := returnClaims{ claims_str, len(claims_str) }
75 |
76 | return c.JSON(http.StatusOK, claims_struct)
77 | }
78 | }
79 |
80 | type postClaimReturn struct {
81 | Itemid string `json:"itemid"`
82 | Error string `json:"error"`
83 | }
84 |
85 | func postClaim(c echo.Context) error {
86 | elem := new(structures.Claim)
87 |
88 | if err := c.Bind(elem); err != nil {
89 | clienterr := postClaimReturn{ "",err.Error() }
90 | return c.JSON(http.StatusBadRequest, clienterr)
91 | }
92 |
93 | res,err := operations.AddClaim(*elem)
94 |
95 | if err!=nil {
96 | response := postElementReturn{ res,err.Error() }
97 | return c.JSON(http.StatusInternalServerError, response)
98 | } else {
99 | response := postElementReturn{ res,"" }
100 | return c.JSON(http.StatusCreated, response)
101 | }
102 | }
--------------------------------------------------------------------------------
/ga10/services/restapi/endpointsHealth.go:
--------------------------------------------------------------------------------
1 | package restapi
2 |
3 | import(
4 | "sync"
5 | "net/http"
6 |
7 | "a10/operations"
8 |
9 | "github.com/labstack/echo/v4"
10 | )
11 |
12 | type healthStructure struct {
13 | Counts counts `json:"counts"`
14 | }
15 |
16 | type counts struct {
17 | Ne int64 `json:"ne"`
18 | Np int64 `json:"Np"`
19 | Nev int64 `json:"Nev"`
20 | Nc int64 `json:"Nc"`
21 | Nr int64 `json:"Nr"`
22 |
23 | Nh int64 `json:"Nh"`
24 | Nrul int64 `json:"Nrul"`
25 | Npol int64 `json:"Npol"`
26 |
27 | Nlog int64 `json:"Nlog"`
28 | }
29 |
30 | // Returns a structure detailing the health of the attestation system
31 | // NB: there was a bit of experimental goroutines here :-)
32 | func objectCount() counts {
33 |
34 | var wg sync.WaitGroup
35 |
36 | wg.Add(9)
37 |
38 | nlog := func() int64 {
39 | defer wg.Done()
40 | return operations.CountLogEntries()
41 | }()
42 |
43 | ne := func() int64 {
44 | defer wg.Done()
45 | return operations.CountElements()
46 | }()
47 |
48 | np := func() int64 {
49 | defer wg.Done()
50 | return operations.CountPolicies()
51 | }()
52 |
53 | nev := func() int64 {
54 | defer wg.Done()
55 | return operations.CountExpectedValues()
56 | }()
57 |
58 | nc := func() int64 {
59 | defer wg.Done()
60 | return operations.CountClaims()
61 | }()
62 |
63 | nr := func() int64 {
64 | defer wg.Done()
65 | return operations.CountResults()
66 | }()
67 |
68 | nh := func() int64 {
69 | defer wg.Done()
70 | return operations.CountOpaqueOjects()
71 | }()
72 |
73 | nrul := func() int64 {
74 | defer wg.Done()
75 | return operations.CountRules()
76 | }()
77 |
78 | npro:= func() int64 {
79 | defer wg.Done()
80 | return operations.CountProtocols()
81 | }()
82 |
83 | wg.Wait()
84 |
85 | return counts{ ne,np,nev,nc,nr,nh,nrul,npro,nlog }
86 | }
87 |
88 |
89 |
90 |
91 | func health(c echo.Context) error {
92 |
93 | hstr := healthStructure{ objectCount() }
94 |
95 | return c.JSON(http.StatusOK, hstr)
96 | }
97 |
--------------------------------------------------------------------------------
/ga10/services/restapi/endpointsLog.go:
--------------------------------------------------------------------------------
1 | package restapi
2 |
3 | import(
4 | "log"
5 | "reflect"
6 |
7 | "net/http"
8 | "strconv"
9 |
10 | "a10/operations"
11 | "a10/structures"
12 | )
13 |
14 | import(
15 | "github.com/labstack/echo/v4"
16 | )
17 |
18 | type returnLogEntries struct {
19 | LogEntries []structures.LogEntry `json:"logentries"`
20 | Length int `json:"length"`
21 | Max int64 `json:"max"`
22 | }
23 |
24 |
25 | func getLogEntries(c echo.Context) error {
26 | max_query := c.QueryParam("max")
27 | max, err := strconv.ParseInt(max_query, 10, 64)
28 | if err != nil {
29 | max=200
30 | }
31 | log.Println("maxtype is ",reflect.TypeOf(max))
32 |
33 |
34 | logentries,err := operations.GetLogEntries(max)
35 |
36 | if err != nil {
37 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err))
38 | } else {
39 | rtn := returnLogEntries{ logentries, len(logentries), max }
40 | return c.JSON(http.StatusOK, rtn)
41 | }
42 | }
43 |
44 |
45 | type returnLogEntriesSince struct {
46 | LogEntries []structures.LogEntry `json:"logentries"`
47 | Length int `json:"length"`
48 | Duration string `json:"duration"`
49 | }
50 |
51 |
52 | func getLogEntriesSince(c echo.Context) error {
53 | duration_query := c.QueryParam("duration")
54 |
55 | logentries,err := operations.GetLogEntriesSince(duration_query)
56 |
57 | if err != nil {
58 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err))
59 | } else {
60 | rtn := returnLogEntriesSince{ logentries, len(logentries), duration_query }
61 | return c.JSON(http.StatusOK, rtn)
62 | }
63 | }
--------------------------------------------------------------------------------
/ga10/services/restapi/endpointsProtocols.go:
--------------------------------------------------------------------------------
1 | package restapi
2 |
3 | import(
4 | "fmt"
5 | "net/http"
6 | "a10/operations"
7 |
8 | "github.com/labstack/echo/v4"
9 | )
10 |
11 |
12 |
13 |
14 | type protocolExternal struct {
15 | Name string `json:"name",bson:"name"`
16 | Description string `json:"description",bson:"description"`
17 | Intents []string `json:"intents",bson:"intents"`
18 | }
19 |
20 |
21 | type returnProtocols struct {
22 | Protocols []protocolExternal `json:"protocols"`
23 | Length int `json:"length"`
24 | }
25 |
26 |
27 |
28 | func getProtocols(c echo.Context) error {
29 | ps := operations.GetProtocols()
30 |
31 | //Convert elems from []structures.Protocol into protocolExternal
32 | var ps_str []protocolExternal
33 | for _,p := range ps {
34 | ps_str = append(ps_str, protocolExternal{ p.Name, p.Description, p.Intents} )
35 | }
36 |
37 | ps_rtn := returnProtocols{ ps_str, len(ps_str) }
38 |
39 | return c.JSON(http.StatusOK, ps_rtn)
40 | }
41 |
42 | func getProtocol(c echo.Context) error {
43 | p,err := operations.GetProtocol(c.Param("name"))
44 |
45 | if err!=nil {
46 | return c.JSON(http.StatusNotFound,fmt.Errorf("No such protocol, %w",err))
47 | } else {
48 | extp := protocolExternal{ p.Name, p.Description, p.Intents}
49 | return c.JSON(http.StatusOK,extp)
50 | }
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/ga10/services/restapi/endpointsResults.go:
--------------------------------------------------------------------------------
1 | package restapi
2 |
3 | import(
4 | "log"
5 | "net/http"
6 | "strconv"
7 |
8 | "a10/operations"
9 | "a10/structures"
10 | )
11 |
12 | import(
13 | "github.com/labstack/echo/v4"
14 | )
15 |
16 | type returnResults struct {
17 | Results []string `json:"results"`
18 | Length int `json:"length"`
19 | }
20 |
21 | func getResults(c echo.Context) error {
22 | Results,err := operations.GetResults()
23 |
24 | if err != nil {
25 | log.Println("err=",err)
26 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err))
27 | } else {
28 | //Convert elems from []structures.ID into a []string
29 | var Results_str []string
30 | for _,e := range Results {
31 | Results_str = append(Results_str,e.ItemID)
32 | }
33 |
34 | //Marshall into JSON
35 | Results_struct := returnResults{ Results_str, len(Results_str) }
36 |
37 | return c.JSON(http.StatusOK, Results_struct)
38 | }
39 | }
40 |
41 | func getResult (c echo.Context) error {
42 | itemid := c.Param("itemid")
43 | Result,err := operations.GetResultByItemID(itemid)
44 |
45 | if err != nil {
46 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err))
47 | } else {
48 | return c.JSON(http.StatusOK, Result)
49 | }
50 | }
51 |
52 | // GetResultsByElementID
53 | func getResultsByElementID (c echo.Context) error {
54 | itemid := c.Param("itemid")
55 | max_query := c.QueryParam("max")
56 | max, err := strconv.ParseInt(max_query, 10, 64)
57 | if err != nil {
58 | max=200
59 | }
60 |
61 | Results,err := operations.GetResultsByElementID(itemid, max)
62 |
63 | if err != nil {
64 | log.Println("err=",err)
65 | return c.JSON(http.StatusInternalServerError,MakeRESTErrorMessage(err))
66 | } else {
67 | //Convert elems from []structures.ID into a []string
68 | var Results_str []string
69 | for _,e := range Results {
70 | Results_str = append(Results_str,e.ItemID)
71 | }
72 |
73 | //Marshall into JSON
74 | Results_struct := returnResults{ Results_str, len(Results_str) }
75 |
76 | return c.JSON(http.StatusOK, Results_struct)
77 | }
78 | }
79 |
80 | type postResultReturn struct {
81 | Itemid string `json:"itemid"`
82 | Error string `json:"error"`
83 | }
84 |
85 | func postResult(c echo.Context) error {
86 | elem := new(structures.Result)
87 |
88 | if err := c.Bind(elem); err != nil {
89 | clienterr := postResultReturn{ "",err.Error() }
90 | return c.JSON(http.StatusBadRequest, clienterr)
91 | }
92 |
93 | res,err := operations.AddResult(*elem)
94 |
95 | if err!=nil {
96 | response := postElementReturn{ res,err.Error() }
97 | return c.JSON(http.StatusInternalServerError, response)
98 | } else {
99 | response := postElementReturn{ res,"" }
100 | return c.JSON(http.StatusCreated, response)
101 | }
102 | }
--------------------------------------------------------------------------------
/ga10/services/restapi/endpointsRules.go:
--------------------------------------------------------------------------------
1 | package restapi
2 |
3 | import(
4 | "fmt"
5 |
6 | "net/http"
7 | "a10/operations"
8 |
9 | "github.com/labstack/echo/v4"
10 | )
11 |
12 | type ruleExternal struct {
13 | Name string `json:"name",bson:"name"`
14 | Description string `json:"description",bson:"description"`
15 | NeedsEV bool `json:"needsev",bson:"needsev"`
16 | }
17 |
18 |
19 | type returnRules struct {
20 | Rules []ruleExternal `json:"rules"`
21 | Length int `json:"length"`
22 | }
23 |
24 | func getRules(c echo.Context) error {
25 | rs := operations.GetRules()
26 |
27 | //Convert rs from []structures.Rule into rulesExternal
28 | var rs_str []ruleExternal
29 | for _,r := range rs {
30 | rs_str = append(rs_str, ruleExternal{ r.Name, r.Description, r.NeedsEV} )
31 | }
32 |
33 | rs_rtn := returnRules{ rs_str, len(rs_str) }
34 |
35 | return c.JSON(http.StatusOK, rs_rtn)
36 |
37 | }
38 |
39 | func getRule(c echo.Context) error {
40 | r,err := operations.GetRule(c.Param("name"))
41 |
42 | if err!=nil {
43 | return c.JSON(http.StatusNotFound,fmt.Errorf("No such rule, %w",err))
44 | } else {
45 | extr := ruleExternal{ r.Name, r.Description, r.NeedsEV}
46 | return c.JSON(http.StatusOK,extr)
47 | }
48 | }
--------------------------------------------------------------------------------
/ga10/services/restapi/resterrors.go:
--------------------------------------------------------------------------------
1 | package restapi
2 |
3 | import(
4 | "fmt"
5 | )
6 |
7 | type restErrorMessage struct {
8 | ErrorMessage string `json:"error",bson:"error"`
9 | }
10 |
11 | func MakeRESTErrorMessage(e error) restErrorMessage{
12 | return restErrorMessage{ fmt.Sprintf("%v",e.Error()) }
13 | }
--------------------------------------------------------------------------------
/ga10/services/webui/attest.go:
--------------------------------------------------------------------------------
1 | package webui
2 |
3 | import(
4 | "fmt"
5 | "net/http"
6 |
7 | "github.com/labstack/echo/v4"
8 |
9 | "a10/operations"
10 | "a10/structures"
11 | )
12 |
13 |
14 | type atteststr struct {
15 | ES []structures.Element
16 | PS []structures.Policy
17 | RS []structures.Rule
18 | }
19 |
20 | func showAttest(c echo.Context) error {
21 | es,_ := operations.GetElementsAll()
22 | ps,_ := operations.GetPoliciesAll()
23 | rs:= operations.GetRules()
24 |
25 | as := atteststr{ es,ps,rs }
26 |
27 | return c.Render(http.StatusOK, "attest.html",as)
28 | }
29 |
30 |
31 | type attestrequest struct {
32 | Eid string `form:"eid"`
33 | Pid string `form:"pid"`
34 | Rn []string `form:"rn"`
35 | Av string `form:"av"`
36 | Pps string `form:"pps"`
37 | Rps string `form:"rps"`
38 | Msg string `form:"msg"`
39 | }
40 |
41 | type multipleresultsummary struct {
42 | ItemID string
43 | RuleName string
44 | Message string
45 | Result structures.ResultValue
46 | EVID string
47 | }
48 |
49 | func processAttest(c echo.Context) error {
50 | var attreq attestrequest
51 |
52 | err := c.Bind(&attreq); if err != nil {
53 | fmt.Printf("Error in binding %v",err.Error())
54 | }
55 |
56 | fmt.Printf("ATTREQ %v\n",attreq)
57 | // Get the objects
58 | e,_ := operations.GetElementByItemID(attreq.Eid)
59 | p,_ := operations.GetPolicyByItemID(attreq.Pid)
60 |
61 | // Open a session
62 | sid,_ := operations.OpenSession(attreq.Msg)
63 | s,_ := operations.GetSessionByItemID(sid)
64 |
65 | // Call attest
66 | // https://stackoverflow.com/questions/47400358/go-converting-json-string-to-mapstringinterface
67 | // should be pps here, but we need to covert the pps from string to map[string]interface{}
68 | empty := make(map[string]interface{})
69 |
70 | // Call attest
71 | cid,err := operations.Attest(e, p, s, empty)
72 |
73 | fmt.Printf("return after attests %v %v\n",err,cid)
74 |
75 | //Check if we are attesting only
76 | // if so, close the session and redirect to the claim page
77 | if attreq.Av=="AO" {
78 | // Close the session now and return - we are not verifying
79 | _ = operations.CloseSession(sid)
80 |
81 | return c.Redirect(http.StatusSeeOther, "/claim/"+cid)
82 | }
83 |
84 | // And now we continue with the verification
85 | // first we need the claim just generated
86 |
87 | cl,_ := operations.GetClaimByItemID(cid)
88 |
89 | // And perform the verifications <--- note the plural
90 | // This bit needs to be parallelised
91 |
92 | for _,rn := range attreq.Rn {
93 | r,_ := operations.GetRule(rn)
94 | fmt.Printf("** verify %v\n",r)
95 |
96 | rid,rv,err := operations.Verify(cl,r,s,empty) // rps conversion goes here
97 | fmt.Printf("results of verify %v - %v - %v\n",err,rv,rid)
98 |
99 | }
100 | // end of parallelism
101 |
102 |
103 | // Close the session
104 | _ = operations.CloseSession(sid)
105 |
106 | // Now we render the multiple (or even just one!) results
107 |
108 | return c.Redirect(http.StatusSeeOther, "/session/"+sid)
109 | }
--------------------------------------------------------------------------------
/ga10/services/webui/claims.go:
--------------------------------------------------------------------------------
1 | package webui
2 |
3 | import(
4 | "fmt"
5 | "net/http"
6 |
7 | "github.com/labstack/echo/v4"
8 |
9 | "a10/operations"
10 | )
11 |
12 |
13 | func showClaims(c echo.Context) error {
14 | es,_ := operations.GetClaimsAll()
15 | fmt.Printf("remdering element %v\n",len(es))
16 |
17 | return c.Render(http.StatusOK, "claims.html",es)
18 | }
19 |
20 | func showClaim(c echo.Context) error {
21 | x,_ := operations.GetClaimByItemID(c.Param("itemid"))
22 |
23 | return c.Render(http.StatusOK, "claim.html",x)
24 | }
--------------------------------------------------------------------------------
/ga10/services/webui/elements.go:
--------------------------------------------------------------------------------
1 | package webui
2 |
3 | import(
4 | "fmt"
5 | "net/http"
6 | "encoding/json"
7 |
8 | "github.com/labstack/echo/v4"
9 |
10 | "a10/operations"
11 | "a10/structures"
12 | )
13 |
14 | type elementsStructure struct {
15 | E structures.Element
16 | CS []structures.Claim
17 | RS []structures.Result
18 | }
19 |
20 | func showElements(c echo.Context) error {
21 | es,_ := operations.GetElementsAll()
22 | fmt.Printf("remdering element %v\n",len(es))
23 |
24 | return c.Render(http.StatusOK, "elements.html",es)
25 | }
26 |
27 | func showElement(c echo.Context) error {
28 | e,_ := operations.GetElementByItemID(c.Param("itemid"))
29 |
30 | fmt.Printf(" cparam is %v and e.ItemId is %v\n",c.Param("itemid"),e.ItemID)
31 |
32 | cs,_ := operations.GetClaimsByElementID(e.ItemID,10)
33 | rs,_ := operations.GetResultsByElementID(e.ItemID,10)
34 |
35 | fmt.Printf("showElement %v\n",c.Param("itemid"))
36 |
37 | es := elementsStructure{ e,cs,rs }
38 |
39 | return c.Render(http.StatusOK, "element.html",es)
40 | }
41 |
42 | func newElement(c echo.Context) error {
43 | return c.Render(http.StatusOK, "editelement.html",nil)
44 | }
45 |
46 |
47 | func processNewElement(c echo.Context) error {
48 | elemdata := c.FormValue("elementdata")
49 |
50 | var newelem structures.Element
51 |
52 | err := json.Unmarshal([]byte(elemdata), &newelem)
53 |
54 | if err != nil {
55 | fmt.Printf("error is %v\n",err.Error())
56 | return c.Redirect(http.StatusSeeOther, "/new/element")
57 | }
58 |
59 | fmt.Printf(" fv%v\n",newelem)
60 | eid,err := operations.AddElement(newelem)
61 | fmt.Printf(" eid=%v,err=%v\n",eid,err)
62 |
63 | return c.Redirect(http.StatusSeeOther, "/elements")
64 | }
--------------------------------------------------------------------------------
/ga10/services/webui/expectedvalues.go:
--------------------------------------------------------------------------------
1 | package webui
2 |
3 | import(
4 | "fmt"
5 | "net/http"
6 |
7 | "github.com/labstack/echo/v4"
8 |
9 | "a10/operations"
10 | "a10/structures"
11 |
12 | )
13 |
14 |
15 | type evstruct struct {
16 | EV structures.ExpectedValue
17 | E structures.Element
18 | P structures.Policy
19 | }
20 |
21 | func showExpectedValues(c echo.Context) error {
22 | fmt.Println("here")
23 | es,_ := operations.GetExpectedValuesAll()
24 |
25 | evs := []evstruct{}
26 |
27 | for _,j := range es {
28 | e,_ := operations.GetElementByItemID(j.ElementID)
29 | p,_ := operations.GetPolicyByItemID(j.PolicyID)
30 | evs = append( evs, evstruct{j,e,p} )
31 | }
32 |
33 |
34 |
35 |
36 | return c.Render(http.StatusOK, "evs.html", evs)
37 | }
38 |
39 | func showExpectedValue(c echo.Context) error {
40 | ev,_ := operations.GetExpectedValueByItemID(c.Param("itemid"))
41 |
42 | e,_ := operations.GetElementByItemID(ev.ElementID)
43 | p,_ := operations.GetPolicyByItemID(ev.PolicyID)
44 |
45 | evstr := evstruct{ ev,e,p}
46 | return c.Render(http.StatusOK, "ev.html",evstr)
47 | }
48 |
49 |
50 | func newExpectedValue(c echo.Context) error {
51 | return c.Render(http.StatusOK, "editexpectedvalue.html",nil)
52 | }
53 |
--------------------------------------------------------------------------------
/ga10/services/webui/homepages.go:
--------------------------------------------------------------------------------
1 | package webui
2 |
3 | import(
4 | "fmt"
5 | "os"
6 | "net/http"
7 |
8 | "github.com/labstack/echo/v4"
9 |
10 | "a10/configuration"
11 | "a10/operations"
12 | )
13 |
14 | type homepagestructure struct {
15 | Nes int
16 | Nps int
17 | Nevs int
18 | Ncs int
19 | Nrs int
20 | Nprs int
21 | Nhs int
22 | Nses int64
23 | Nrus int
24 | Nlog int64
25 | Szlog int64
26 | Cfg *configuration.ConfigurationStruct
27 | }
28 |
29 | func homepage(c echo.Context) error {
30 | var hps homepagestructure
31 |
32 | es,_ := operations.GetElements()
33 | ps,_ := operations.GetPolicies()
34 | evs,_ := operations.GetExpectedValues()
35 | cs,_ := operations.GetClaims()
36 | rs,_ := operations.GetResults()
37 | nprs := operations.GetProtocols()
38 | nhs,_ := operations.GetOpaqueObjects()
39 | nrus := operations.GetRules()
40 |
41 | hps.Nes = len(es)
42 | hps.Nps = len(ps)
43 | hps.Nevs = len(evs)
44 | hps.Ncs = len(cs)
45 | hps.Nrs = len(rs)
46 |
47 | hps.Nprs = len(nprs)
48 | hps.Nhs = len(nhs)
49 | hps.Nrus = len(nrus)
50 |
51 | hps.Nlog = operations.CountLogEntries()
52 | hps.Nses = operations.CountSessions()
53 |
54 | lsz,lerr := os.Stat(configuration.ConfigData.Logging.LogFileLocation)
55 | if lerr != nil {
56 | hps.Szlog = -1
57 | } else {
58 | hps.Szlog = lsz.Size()
59 | }
60 |
61 | hps.Cfg = configuration.ConfigData
62 |
63 | fmt.Printf("hps is %v\n",hps)
64 |
65 | return c.Render(http.StatusOK, "home.html",hps)
66 | }
67 |
68 |
69 |
70 | func helppage(c echo.Context) error {
71 | return c.Render(http.StatusOK, "help.html", nil)
72 | }
73 |
74 | func aboutpage(c echo.Context) error {
75 | return c.Render(http.StatusOK, "about.html", nil)
76 | }
--------------------------------------------------------------------------------
/ga10/services/webui/log.go:
--------------------------------------------------------------------------------
1 | package webui
2 |
3 | import(
4 | "net/http"
5 | "strconv"
6 |
7 | "github.com/labstack/echo/v4"
8 |
9 | "a10/operations"
10 | "a10/structures"
11 | )
12 |
13 | type logstr struct {
14 | LogEntries []structures.LogEntry
15 | Count int64
16 | Amount int64
17 | Duration string
18 | }
19 |
20 | func showLog(c echo.Context) error {
21 | max_query := c.QueryParam("max")
22 | max, err := strconv.ParseInt(max_query, 10, 64)
23 | if err != nil {
24 | max=200
25 | }
26 |
27 | es,_ := operations.GetLogEntries(max)
28 | nl := operations.CountLogEntries()
29 |
30 | ls := logstr{ es, nl, max, "always"}
31 |
32 | return c.Render(http.StatusOK, "log.html",ls)
33 | }
34 |
35 |
36 |
37 | func showLogSince(c echo.Context) error {
38 | duration := c.QueryParam("duration")
39 |
40 | es,_ := operations.GetLogEntriesSince(duration)
41 | nl := int64(len(es))
42 |
43 | ls := logstr{ es, nl, nl, duration }
44 |
45 | return c.Render(http.StatusOK, "log.html",ls)
46 | }
--------------------------------------------------------------------------------
/ga10/services/webui/opaqueobjects.go:
--------------------------------------------------------------------------------
1 | package webui
2 |
3 | import(
4 | "net/http"
5 |
6 | "github.com/labstack/echo/v4"
7 |
8 | "a10/operations"
9 | )
10 |
11 |
12 | func showOpaqueObjects(c echo.Context) error {
13 | os,_ := operations.GetOpaqueObjects()
14 |
15 | return c.Render(http.StatusOK, "opaqueobjects.html",os)
16 | }
17 |
18 | func showOpaqueObject(c echo.Context) error {
19 | o,_ := operations.GetOpaqueObjectByValue(c.Param("name"))
20 |
21 | return c.Render(http.StatusOK, "opaqueobject.html", o)
22 | }
--------------------------------------------------------------------------------
/ga10/services/webui/policies.go:
--------------------------------------------------------------------------------
1 | package webui
2 |
3 | import (
4 | "encoding/json"
5 | "fmt"
6 | "net/http"
7 |
8 | "github.com/labstack/echo/v4"
9 |
10 | "a10/operations"
11 | "a10/structures"
12 | )
13 |
14 | func showPolicies(c echo.Context) error {
15 | es, _ := operations.GetPoliciesAll()
16 | return c.Render(http.StatusOK, "policies.html", es)
17 | }
18 |
19 | func showPolicy(c echo.Context) error {
20 | e, _ := operations.GetPolicyByItemID(c.Param("itemid"))
21 | return c.Render(http.StatusOK, "policy.html", e)
22 | }
23 |
24 | func newPolicy(c echo.Context) error {
25 | return c.Render(http.StatusOK, "editpolicy.html", nil)
26 | }
27 |
28 | func processNewPolicy(c echo.Context) error {
29 | elemdata := c.FormValue("policydata")
30 |
31 | var newPolicy structures.Policy
32 |
33 | err := json.Unmarshal([]byte(elemdata), &newPolicy)
34 |
35 | if err != nil {
36 | fmt.Printf("error is %v\n", err.Error())
37 | return c.Redirect(http.StatusSeeOther, "/new/policy")
38 | }
39 |
40 | fmt.Printf(" fv%v\n", newPolicy)
41 | eid, err := operations.AddPolicy(newPolicy)
42 | fmt.Printf(" eid=%v,err=%v\n", eid, err)
43 |
44 | return c.Redirect(http.StatusSeeOther, "/policies")
45 | }
46 |
--------------------------------------------------------------------------------
/ga10/services/webui/protocols.go:
--------------------------------------------------------------------------------
1 | package webui
2 |
3 | import(
4 | "net/http"
5 |
6 | "github.com/labstack/echo/v4"
7 |
8 | "a10/operations"
9 | )
10 |
11 |
12 | func showProtocols(c echo.Context) error {
13 | ps := operations.GetProtocols()
14 |
15 | return c.Render(http.StatusOK, "protocols.html",ps)
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/ga10/services/webui/results.go:
--------------------------------------------------------------------------------
1 | package webui
2 |
3 | import(
4 | "net/http"
5 |
6 | "github.com/labstack/echo/v4"
7 |
8 | "a10/operations"
9 | "a10/structures"
10 | )
11 |
12 |
13 | type resultsstr struct {
14 | ItemID string
15 | RuleName string
16 | VerifiedAt structures.Timestamp
17 | Result structures.ResultValue
18 | EVEName string
19 | EVEID string
20 | EVPName string
21 | EVPID string
22 | EV_Name string
23 | EV_ItemID string
24 | ClaimID string
25 | SessionID string
26 | Message string
27 | Footer structures.ResultFooter
28 | }
29 |
30 | func showResults(c echo.Context) error {
31 |
32 | rsstr := []resultsstr{}
33 |
34 |
35 | rs,_ := operations.GetResultsAll()
36 | for _,j := range rs {
37 | ev,_ := operations.GetExpectedValueByItemID(j.ExpectedValue.ItemID)
38 | e,_ := operations.GetElementByItemID(ev.ElementID)
39 | p,_ := operations.GetPolicyByItemID(ev.PolicyID)
40 |
41 | rsstr = append( rsstr, resultsstr{ j.ItemID, j.RuleName,j.VerifiedAt,j.Result,e.Name,e.ItemID,p.Name,p.ItemID,ev.Name,ev.ItemID,j.ClaimID,j.Session.ItemID,j.Message,j.Footer } )
42 | }
43 |
44 |
45 | return c.Render(http.StatusOK, "results.html", rsstr)
46 | }
47 |
48 |
49 |
50 | type resultsstrext struct {
51 | R resultsstr
52 | }
53 |
54 | func showResult(c echo.Context) error {
55 | r,_ := operations.GetResultByItemID(c.Param("itemid"))
56 |
57 | ev,_ := operations.GetExpectedValueByItemID(r.ExpectedValue.ItemID)
58 | e,_ := operations.GetElementByItemID(ev.ElementID)
59 | p,_ := operations.GetPolicyByItemID(ev.PolicyID)
60 |
61 | rsstr := resultsstr{ r.ItemID, r.RuleName, r.VerifiedAt, r.Result,e.Name,e.ItemID,p.Name,p.ItemID,ev.Name,ev.ItemID,r.ClaimID,r.Session.ItemID,r.Message,r.Footer }
62 | rsstrext := resultsstrext{ rsstr }
63 |
64 | return c.Render(http.StatusOK, "result.html", rsstrext)
65 | }
66 |
--------------------------------------------------------------------------------
/ga10/services/webui/rules.go:
--------------------------------------------------------------------------------
1 | package webui
2 |
3 | import(
4 | "net/http"
5 |
6 | "github.com/labstack/echo/v4"
7 |
8 | "a10/operations"
9 | )
10 |
11 |
12 | func showRules(c echo.Context) error {
13 | rs := operations.GetRules()
14 |
15 | return c.Render(http.StatusOK, "rules.html",rs)
16 | }
17 |
18 |
--------------------------------------------------------------------------------
/ga10/services/webui/sessions.go:
--------------------------------------------------------------------------------
1 | package webui
2 |
3 | import(
4 | "net/http"
5 | "github.com/labstack/echo/v4"
6 |
7 | "a10/operations"
8 | "a10/structures"
9 | )
10 |
11 | type claimsummary struct {
12 | ItemID string
13 | BodyType string
14 | }
15 |
16 | type resultsummary struct{
17 | ItemID string
18 | Result structures.ResultValue
19 | RuleName string
20 | VerifiedAt structures.Timestamp
21 | }
22 |
23 |
24 | func showSessions(c echo.Context) error {
25 | s,_ := operations.GetSessionsAll()
26 |
27 | return c.Render(http.StatusOK, "sessions.html",s)
28 | }
29 |
30 |
31 |
32 |
33 | type claimanalytics struct {
34 | Valid int
35 | Errs int
36 | }
37 |
38 | type resultanalytics struct {
39 | Pass int
40 | Fail int
41 | Verifyfail int
42 | Verifycallattempt int
43 | Noresult int
44 | Missineexpectedvalue int
45 | Rulecallfailure int
46 | Unsetresultvalue int
47 | }
48 |
49 | type sessionsummary struct {
50 | S structures.Session
51 | CS []claimsummary
52 | RS []resultsummary
53 | CA claimanalytics
54 | RA resultanalytics
55 | }
56 |
57 |
58 | func showSession(c echo.Context) error {
59 | s,_ := operations.GetSessionByItemID(c.Param("itemid"))
60 |
61 | cs := make([]claimsummary,0)
62 | for _,i := range s.ClaimList {
63 | cl,_ := operations.GetClaimByItemID(i)
64 | cs = append(cs, claimsummary{ cl.ItemID, cl.BodyType })
65 | }
66 |
67 | rs := make([]resultsummary,0)
68 | for _,i := range s.ResultList {
69 | rl,_ := operations.GetResultByItemID(i)
70 | rs = append(rs, resultsummary{ rl.ItemID, rl.Result, rl.RuleName, rl.VerifiedAt })
71 | }
72 |
73 | sstr := sessionsummary{ s, cs, rs, genclaimanalytics(cs), genresultanalytics(rs) }
74 | return c.Render(http.StatusOK, "session.html", sstr)
75 | }
76 |
77 |
78 | func genclaimanalytics( cs []claimsummary ) claimanalytics{
79 | var valid int = 0
80 | var errs int = 0
81 |
82 | for _,c := range cs {
83 | if c.BodyType == "*ERROR" {
84 | errs ++
85 | } else {
86 | valid ++
87 | }
88 | }
89 |
90 | return claimanalytics{ valid, errs }
91 | }
92 |
93 | func genresultanalytics( rs []resultsummary ) resultanalytics{
94 | var pass int = 0
95 | var fail int = 0
96 | var verifyfail int = 0
97 | var verifycallattempt int = 0
98 | var noresult int = 0
99 | var missineexpectedvalue int = 0
100 | var rulecallfailure int = 0
101 | var unsetresultvalue int = 0
102 |
103 | for _,r := range rs {
104 | switch r.Result {
105 | case structures.Success :
106 | pass ++
107 | case structures.Fail :
108 | fail ++
109 | case structures.VerifyCallFailure :
110 | verifyfail ++
111 | case structures.VerifyClaimErrorAttempt:
112 | verifycallattempt ++
113 | case structures.NoResult :
114 | noresult ++
115 | case structures.MissingExpectedValue :
116 | missineexpectedvalue ++
117 | case structures.RuleCallFailure :
118 | rulecallfailure ++
119 | case structures.UnsetResultValue :
120 | unsetresultvalue ++
121 | }
122 |
123 | }
124 |
125 | return resultanalytics{ pass,fail,verifyfail,verifycallattempt,noresult,missineexpectedvalue,rulecallfailure,unsetresultvalue }
126 | }
127 |
128 |
--------------------------------------------------------------------------------
/ga10/services/webui/templatefunctions.go:
--------------------------------------------------------------------------------
1 | package webui
2 |
3 | import (
4 | "fmt"
5 | "strconv"
6 | "time"
7 |
8 | "encoding/base64"
9 | "encoding/hex"
10 |
11 | "a10/structures"
12 | "a10/utilities"
13 |
14 | "github.com/google/go-tpm/legacy/tpm2"
15 | )
16 |
17 | // No idea if this works but it is supposed to be in the html files
18 | func EpochToUTC(epoch structures.Timestamp) string {
19 | sec, err := strconv.ParseInt(fmt.Sprintf("%v", epoch), 10, 64)
20 | if err != nil {
21 | t := time.Unix(0, 0)
22 | return fmt.Sprintf("%v", t.UTC())
23 | }
24 | t := time.Unix(0, sec)
25 | return fmt.Sprintf("%v", t.UTC())
26 | }
27 |
28 | func DefaultMessage() string {
29 | return "Single invocation from WebUI at " + EpochToUTC(utilities.MakeTimestamp())
30 | }
31 |
32 | func Base64decode(u string) string {
33 | d, _ := base64.StdEncoding.DecodeString(u)
34 | return string(d)
35 | }
36 |
37 | func EncodeAsHexString(b []byte) string {
38 | return hex.EncodeToString(b)
39 | }
40 |
41 | func TCGAlg(h int32) string {
42 | return tpm2.Algorithm(h).String()
43 | }
44 |
--------------------------------------------------------------------------------
/ga10/services/webui/templates/attest.html:
--------------------------------------------------------------------------------
1 | {{define "content"}}
2 |
Attest
3 |
4 |
5 |
6 |
84 |
85 |
86 |
87 |
88 | {{end}}
--------------------------------------------------------------------------------
/ga10/services/webui/templates/attestsummary.html:
--------------------------------------------------------------------------------
1 | {{define "content"}}
2 | Session
3 |
4 |
5 |
6 |
7 | Field |
8 | Value |
9 |
10 |
11 |
12 | ItemID | {{ .ItemID }} |
13 | Opened | {{ epochToUTC .Timing.Opened }} |
14 | Closed
15 | {{ if eq .Timing.Closed "0" }}
16 | | Session still open |
17 | {{ else }}
18 | {{ epochToUTC .Timing.Closed }} |
19 | {{ end }}
20 |
21 | #Claims | {{ len .ClaimList }} |
22 | #Results | {{ len .ResultList }} |
23 | Message | {{ .Message }} |
24 |
25 |
26 |
27 |
28 |
29 | Claims
30 |
31 |
32 | {{ range .ClaimList }}
33 | - {{ . }}
34 | {{ end}}
35 |
36 |
37 |
38 | Results
39 |
40 |
41 | {{ range .ResultList }}
42 | - {{ . }}
43 | {{ end}}
44 |
45 |
46 |
47 | {{end}}
48 |
49 |
--------------------------------------------------------------------------------
/ga10/services/webui/templates/base.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | GA10 Web User Interface
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
80 |
81 |
82 |
83 |
84 | {{block "content" .}}{{end}}
85 |
86 |
87 |
88 |
89 |
--------------------------------------------------------------------------------
/ga10/services/webui/templates/claim.html:
--------------------------------------------------------------------------------
1 | {{define "content"}}
2 |
3 | Claim
4 |
5 |
6 |
7 |
8 |
9 |
Header
10 |
11 |
12 |
13 | Field |
14 | Value |
15 |
16 |
17 |
18 | ItemID | {{ .ItemID }} |
19 | BodyType | {{ .BodyType }} |
20 | Element | {{ .Header.Element.Name }} |
21 | -- Protocol | {{ .Header.Element.Protocol }} |
22 | -- Endpoint | {{ .Header.Element.Endpoint }} |
23 | Policy | {{ .Header.Policy.Name }} |
24 | -- Intent | {{ .Header.Policy.Intent }} |
25 | Session | {{ .Header.Session.ItemID }} |
26 | Additional Parameters | {{ .Header.AdditionalParameters }} |
27 | Call Parameters | {{ .Header.CallParameters }} |
28 | Requested | {{ epochToUTC .Header.Timing.Requested }} |
29 | Received | {{ epochToUTC .Header.Timing.Received }} |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
Footer
37 |
38 |
39 |
40 | Field |
41 | Value |
42 |
43 |
44 |
45 | Hash | {{ encodeAsHexString .Footer.Hash }} |
46 | Signature | {{ encodeAsHexString .Footer.Signature }} |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 | Body:
55 |
56 | {{ if eq .BodyType "*ERROR" }}
57 | {{ .BodyType }}
58 | {{ template "claim_ERROR.html" .Body }}
59 | {{ end }}
60 |
61 | {{ if eq .BodyType "sys/info" }}
62 | {{ .BodyType }}
63 | {{ template "genericList.html" .Body }}
64 | {{ end }}
65 |
66 | {{ if eq .BodyType "ima/asciilog" }}
67 | {{ .BodyType }}
68 | {{ template "claim_ima.html" .Body }}
69 | {{ end }}
70 |
71 | {{ if eq .BodyType "tpm2/pcrs" }}
72 | {{ .BodyType }}
73 | {{ template "claim_tpm2pcrs.html" .Body }}
74 | {{ end }}
75 |
76 | {{ if eq .BodyType "tpm2/quote" }}
77 | {{ .BodyType }}
78 | {{ template "claim_quote.html" .Body.parsed }}
79 | {{ end }}
80 |
81 |
82 | Raw
83 | {{ .Body }}
84 |
85 | {{end}}
86 |
--------------------------------------------------------------------------------
/ga10/services/webui/templates/claim_ERROR.html:
--------------------------------------------------------------------------------
1 | {{define "claim_ERROR.html"}}
2 |
3 |
4 | {{ range $key, $value := .ERROR }}
5 | {{ $key }} | {{ $value }} |
6 | {{ end }}
7 |
8 |
9 | {{end}}
10 |
11 |
12 |
--------------------------------------------------------------------------------
/ga10/services/webui/templates/claim_ima.html:
--------------------------------------------------------------------------------
1 | {{define "claim_ima.html"}}
2 |
3 |
4 |
5 |
6 |
7 | Field |
8 | Value |
9 |
10 |
11 |
12 | Encoding details | {{ .encoded }} {{ .encodedlength }} bytes encoded, {{ .unencodedlength }} bytes original |
13 | IMA ASCII Log | {{ base64decode .asciilog }} |
14 |
15 |
16 |
17 | {{end}}
18 |
19 |
20 |
--------------------------------------------------------------------------------
/ga10/services/webui/templates/claim_quote.html:
--------------------------------------------------------------------------------
1 | {{define "claim_quote.html"}}
2 |
3 |
4 |
5 | PCR Digest | {{ .quote.AttestedQuoteInfo.PCRDigest }} |
6 | PCR Selection | {{ tcgAlg .quote.AttestedQuoteInfo.PCRSelection.Hash }} :
7 | {{ range .quote.AttestedQuoteInfo.PCRSelection.PCRs }}
8 | {{ . }}
9 | {{ end }}
10 | |
11 | Firmware | {{ .quote.FirmwareVersion }} |
12 |
13 | Magic & Type | {{ .quote.Magic }}, {{ .quote.Type }} |
14 | Extra Data | {{ .quote.ExtraData }} |
15 |
16 | Clock | {{ .quote.ClockInfo.Clock }} |
17 | Reset Count | {{ .quote.ClockInfo.ResetCount }} |
18 | Restart Count | {{ .quote.ClockInfo.RestartCount }} |
19 | Safe |
20 | {{ if .quote.ClockInfo.Safe}}
21 | Safe ({{ .quote.ClockInfo.Safe }})
22 | {{ else }}
23 | Unsafe ({{ .quote.ClockInfo.Safe }})
24 | {{ end }}
25 | |
26 |
27 | Qualified Signer | {{ .quote.QualifiedSigner.Digest.Alg }} {{ .quote.QualifiedSigner.Digest.Value }} |
28 |
29 |
30 | Signing Algorithm | {{ tcgAlg .signature.Alg }} |
31 | {{ if eq .signature.Alg 20 }}
32 | RSA | {{ tcgAlg .signature.RSA.HashAlg }} {{ .signature.RSA.Signature }} |
33 | {{ else }}
34 | ECC | {{ tcgAlg .signature.ECC.HashAlg }} {{ .signature.ECC.Signature }} |
35 | {{ end }}
36 |
37 |
38 |
39 |
40 |
41 |
42 | {{end}}
43 |
44 |
--------------------------------------------------------------------------------
/ga10/services/webui/templates/claim_tpm2pcrs.html:
--------------------------------------------------------------------------------
1 | {{define "claim_tpm2pcrs.html"}}
2 |
3 |
4 | {{ range $key, $value := . }}
5 | {{ $key }} |
6 |
7 |
8 |
9 |
10 | {{ range $pkey, $pvalue := $value }}
11 | {{ $pkey }} |
12 | {{ $pvalue }} |
13 |
14 | {{ end }}
15 |
16 |
17 |
18 | |
19 | {{ end }}
20 |
21 |
22 | {{end}}
23 |
24 |
--------------------------------------------------------------------------------
/ga10/services/webui/templates/claims.html:
--------------------------------------------------------------------------------
1 | {{define "content"}}
2 | Claims
3 |
4 |
5 |
6 | BodyType |
7 | Requested |
8 | Received |
9 | Element |
10 | Policy |
11 | Session |
12 |
13 |
14 |
15 | {{ range . }}
16 | {{ if eq .BodyType "*ERROR"}}
17 |
18 | {{else}}
19 |
20 | {{end}}
21 | {{ .BodyType }} |
22 | {{ epochToUTC .Header.Timing.Requested }} |
23 | {{ epochToUTC .Header.Timing.Received }} |
24 | {{ .Header.Element.Name }} |
25 | {{ .Header.Policy.Name }} |
26 | {{ .Header.Session.ItemID }} |
27 | {{end}}
28 |
29 |
30 | {{end}}
31 |
32 |
--------------------------------------------------------------------------------
/ga10/services/webui/templates/editelement.html:
--------------------------------------------------------------------------------
1 | {{define "content"}}
2 | Element
3 |
4 |