diff --git a/.github/CODEOWNERS b/.github/CODEOWNERS new file mode 100644 index 0000000..7a3d1ff --- /dev/null +++ b/.github/CODEOWNERS @@ -0,0 +1,4 @@ +# SPDX-FileCopyrightText: 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +* @omec-project/5gc-maintainers diff --git a/.github/dependabot.yml b/.github/dependabot.yml index 4528d1d..95425fa 100644 --- a/.github/dependabot.yml +++ b/.github/dependabot.yml @@ -19,3 +19,15 @@ updates: day: "sunday" time: "21:00" timezone: "America/Los_Angeles" + + - package-ecosystem: github-actions + directory: / + schedule: + interval: "weekly" + day: "sunday" + time: "21:00" + timezone: "America/Los_Angeles" + groups: + actions-deps: + patterns: + - "*" diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index b8af934..465bdf5 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2024 Intel Corporation +name: CI Pipeline + on: pull_request: branches: @@ -8,43 +10,110 @@ on: branches: - main +permissions: + contents: read + jobs: build: - uses: omec-project/.github/.github/workflows/build.yml@main + permissions: + contents: read + actions: read + security-events: write + id-token: write + attestations: write + uses: omec-project/.github/.github/workflows/build.yml@76c248f1621bfe102956c558ea8cecfe5df143bf # v0.0.3 with: branch_name: ${{ github.ref }} docker-build: - uses: omec-project/.github/.github/workflows/docker-build.yml@main + permissions: + contents: read + packages: write + id-token: write + attestations: write + uses: omec-project/.github/.github/workflows/docker-build.yml@76c248f1621bfe102956c558ea8cecfe5df143bf # v0.0.3 with: branch_name: ${{ github.ref }} static-analysis: - uses: omec-project/.github/.github/workflows/static-analysis.yml@main + permissions: + contents: read + security-events: write + actions: read + id-token: write + attestations: write + uses: omec-project/.github/.github/workflows/static-analysis.yml@76c248f1621bfe102956c558ea8cecfe5df143bf # v0.0.3 with: branch_name: ${{ github.ref }} lint: - uses: omec-project/.github/.github/workflows/lint.yml@main + permissions: + contents: read + checks: write + id-token: write + attestations: write + uses: omec-project/.github/.github/workflows/lint.yml@76c248f1621bfe102956c558ea8cecfe5df143bf # v0.0.3 with: branch_name: ${{ github.ref }} hadolint: - uses: omec-project/.github/.github/workflows/hadolint.yml@main + permissions: + contents: read + security-events: write + id-token: write + attestations: write + uses: omec-project/.github/.github/workflows/hadolint.yml@76c248f1621bfe102956c558ea8cecfe5df143bf # v0.0.3 with: branch_name: ${{ github.ref }} license-check: - uses: omec-project/.github/.github/workflows/license-check.yml@main + permissions: + contents: read + id-token: write + attestations: write + uses: omec-project/.github/.github/workflows/license-check.yml@76c248f1621bfe102956c558ea8cecfe5df143bf # v0.0.3 with: branch_name: ${{ github.ref }} fossa-scan: - uses: omec-project/.github/.github/workflows/fossa-scan.yml@main + permissions: + contents: read + security-events: write + id-token: write + attestations: write + uses: omec-project/.github/.github/workflows/fossa-scan.yml@76c248f1621bfe102956c558ea8cecfe5df143bf # v0.0.3 with: branch_name: ${{ github.ref }} unit-tests: - uses: omec-project/.github/.github/workflows/unit-test.yml@main + permissions: + contents: read + checks: write + id-token: write + attestations: write + uses: omec-project/.github/.github/workflows/unit-test.yml@76c248f1621bfe102956c558ea8cecfe5df143bf # v0.0.3 + with: + branch_name: ${{ github.ref }} + + analysis: + if: github.repository_owner == 'omec-project' + permissions: + actions: read + artifact-metadata: read + attestations: read + checks: read + contents: read + deployments: read + discussions: read + id-token: write + issues: read + models: read + packages: read + pages: read + pull-requests: read + repository-projects: read + security-events: write + statuses: read + uses: omec-project/.github/.github/workflows/scorecard-analysis.yml@76c248f1621bfe102956c558ea8cecfe5df143bf # v0.0.3 with: branch_name: ${{ github.ref }} diff --git a/.github/workflows/push.yml b/.github/workflows/push.yml index b61ae48..964d194 100644 --- a/.github/workflows/push.yml +++ b/.github/workflows/push.yml @@ -1,5 +1,7 @@ # SPDX-License-Identifier: Apache-2.0 # Copyright 2024 Intel Corporation +name: Release Pipeline + on: push: branches: @@ -7,14 +9,27 @@ on: paths: - "VERSION" +permissions: + contents: read + jobs: tag-github: - uses: omec-project/.github/.github/workflows/tag-github.yml@main + permissions: + contents: write + actions: read + id-token: write + uses: omec-project/.github/.github/workflows/tag-github.yml@76c248f1621bfe102956c558ea8cecfe5df143bf # v0.0.3 secrets: inherit release-image: needs: tag-github - uses: omec-project/.github/.github/workflows/release-image.yml@main + permissions: + contents: read + packages: write + actions: read + id-token: write + attestations: write + uses: omec-project/.github/.github/workflows/release-image.yml@76c248f1621bfe102956c558ea8cecfe5df143bf # v0.0.3 with: changed: ${{ needs.tag-github.outputs.changed }} version: ${{ needs.tag-github.outputs.version }} @@ -22,7 +37,12 @@ jobs: update-version: needs: tag-github - uses: omec-project/.github/.github/workflows/update-version.yml@main + permissions: + contents: write + pull-requests: write + actions: read + id-token: write + uses: omec-project/.github/.github/workflows/update-version.yml@76c248f1621bfe102956c558ea8cecfe5df143bf # v0.0.3 with: changed: ${{ needs.tag-github.outputs.changed }} version: ${{ needs.tag-github.outputs.version }} @@ -30,7 +50,11 @@ jobs: branch-release: needs: tag-github - uses: omec-project/.github/.github/workflows/branch-release.yml@main + permissions: + contents: write + actions: read + id-token: write + uses: omec-project/.github/.github/workflows/branch-release.yml@76c248f1621bfe102956c558ea8cecfe5df143bf # v0.0.3 with: release_branch: ${{ needs.tag-github.outputs.release_branch }} version_branch: ${{ needs.tag-github.outputs.version_branch }} diff --git a/.github/workflows/stale.yml b/.github/workflows/stale.yml index 563219f..0b6cbda 100644 --- a/.github/workflows/stale.yml +++ b/.github/workflows/stale.yml @@ -4,9 +4,19 @@ on: schedule: - cron: "0 0 * * *" +permissions: + issues: write + pull-requests: write + contents: read + jobs: stale: - uses: omec-project/.github/.github/workflows/stale-issue.yml@main + permissions: + issues: write + pull-requests: write + contents: read + actions: read + uses: omec-project/.github/.github/workflows/stale-issue.yml@76c248f1621bfe102956c558ea8cecfe5df143bf # v0.0.3 with: days_before_stale: 120 days_before_close: 15 diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml new file mode 100644 index 0000000..96d85e6 --- /dev/null +++ b/.pre-commit-config.yaml @@ -0,0 +1,17 @@ +# SPDX-FileCopyrightText: 2025 Intel Corporation +# SPDX-License-Identifier: Apache-2.0 + +repos: +- repo: https://github.com/gitleaks/gitleaks + rev: v8.29.0 + hooks: + - id: gitleaks +- repo: https://github.com/golangci/golangci-lint + rev: v2.6.1 + hooks: + - id: golangci-lint +- repo: https://github.com/pre-commit/pre-commit-hooks + rev: v6.0.0 + hooks: + - id: end-of-file-fixer + - id: trailing-whitespace diff --git a/Dockerfile b/Dockerfile index 38c2206..b3da0c2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,7 @@ # SPDX-License-Identifier: Apache-2.0 # -FROM golang:1.24.5-bookworm AS builder +FROM golang:1.25.5-bookworm@sha256:2c7c65601b020ee79db4c1a32ebee0bf3d6b298969ec683e24fcbea29305f10e AS builder RUN apt-get update && \ apt-get -y install --no-install-recommends \ @@ -15,7 +15,7 @@ WORKDIR $GOPATH/src/simapp COPY . . RUN make all -FROM alpine:3.22 AS simapp +FROM alpine:3.23@sha256:865b95f46d98cf867a156fe4a135ad3fe50d2056aa3f25ed31662dff6da4eb62 AS simapp LABEL maintainer="Aether SD-Core " \ description="Aether open source 5G Core Network" \ diff --git a/README.md b/README.md index 129f400..f52f51f 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ Copyright 2021-present Open Networking Foundation SPDX-License-Identifier: Apache-2.0 --> [![Go Report Card](https://goreportcard.com/badge/github.com/omec-project/simapp)](https://goreportcard.com/report/github.com/omec-project/simapp) +[![OpenSSF Scorecard](https://api.scorecard.dev/projects/github.com/omec-project/simapp/badge)](https://scorecard.dev/viewer/?uri=github.com/omec-project/simapp) # Simapp ## Sim subscription app for Aether @@ -22,7 +23,7 @@ slices as well - In case ROC is running in the deployment then network slices can be configured from ROC -## Reach out to us thorugh +## Reach out to us through 1. #sdcore-dev channel in [ONF Community Slack](https://onf-community.slack.com/) 2. Extensive SD-Core documentation can be found at [SD-Core Documentation](https://docs.sd-core.opennetworking.org/main/index.html) 3. Raise Github issues diff --git a/docs/SECURITY.md b/docs/SECURITY.md new file mode 100644 index 0000000..3dd6611 --- /dev/null +++ b/docs/SECURITY.md @@ -0,0 +1,41 @@ + +# Security Policy + +## Supported Versions + +We release patches for security vulnerabilities in the following versions: + +| Version | Supported | +| ------- | ------------------ | +| 1.x.x | :white_check_mark: | + +## Reporting a Vulnerability + +If you discover a security vulnerability, please: + +1. **DO NOT** create a public GitHub issue +2. Email us at: info@aetherproject.org +3. Include detailed information about the vulnerability +4. Allow us reasonable time to address the issue before public disclosure + +### What to Include + +- Description of the vulnerability +- Steps to reproduce the issue +- Potential impact assessment +- Any proof-of-concept code (if applicable) + +## Security Best Practices + +When using this project: +- Keep dependencies up to date +- Use the latest supported version +- Follow secure coding practices +- Regularly audit your implementation + +## Contact + +Please see [here](https://github.com/omec-project/simapp/?tab=readme-ov-file#reach-out-to-us-through) diff --git a/go.mod b/go.mod index f2f1bc4..e664c70 100644 --- a/go.mod +++ b/go.mod @@ -4,24 +4,24 @@ go 1.24.0 require ( github.com/fsnotify/fsnotify v1.9.0 - github.com/spf13/viper v1.20.1 - github.com/urfave/cli/v3 v3.3.8 - go.uber.org/zap v1.27.0 - golang.org/x/net v0.42.0 - gopkg.in/yaml.v2 v2.4.0 + github.com/spf13/viper v1.21.0 + github.com/urfave/cli/v3 v3.6.1 + go.uber.org/zap v1.27.1 + go.yaml.in/yaml/v4 v4.0.0-rc.3 + golang.org/x/net v0.48.0 ) require ( - github.com/go-viper/mapstructure/v2 v2.3.0 // indirect + github.com/go-viper/mapstructure/v2 v2.4.0 // indirect github.com/pelletier/go-toml/v2 v2.2.4 // indirect - github.com/sagikazarmark/locafero v0.9.0 // indirect - github.com/sourcegraph/conc v0.3.0 // indirect - github.com/spf13/afero v1.14.0 // indirect - github.com/spf13/cast v1.9.2 // indirect - github.com/spf13/pflag v1.0.6 // indirect + github.com/sagikazarmark/locafero v0.11.0 // indirect + github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 // indirect + github.com/spf13/afero v1.15.0 // indirect + github.com/spf13/cast v1.10.0 // indirect + github.com/spf13/pflag v1.0.10 // indirect github.com/subosito/gotenv v1.6.0 // indirect go.uber.org/multierr v1.11.0 // indirect - golang.org/x/sys v0.34.0 // indirect - golang.org/x/text v0.27.0 // indirect - gopkg.in/yaml.v3 v3.0.1 // indirect + go.yaml.in/yaml/v3 v3.0.4 // indirect + golang.org/x/sys v0.39.0 // indirect + golang.org/x/text v0.32.0 // indirect ) diff --git a/go.sum b/go.sum index 9a17a09..3b75ccf 100644 --- a/go.sum +++ b/go.sum @@ -4,8 +4,8 @@ github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHk github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0= github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k= github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0= -github.com/go-viper/mapstructure/v2 v2.3.0 h1:27XbWsHIqhbdR5TIC911OfYvgSaW93HM+dX7970Q7jk= -github.com/go-viper/mapstructure/v2 v2.3.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= +github.com/go-viper/mapstructure/v2 v2.4.0 h1:EBsztssimR/CONLSZZ04E8qAkxNYq4Qp9LvH92wZUgs= +github.com/go-viper/mapstructure/v2 v2.4.0/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM= github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI= github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= @@ -18,40 +18,42 @@ github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZb github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8= github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= -github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k= -github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk= -github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo= -github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0= -github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA= -github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo= -github.com/spf13/cast v1.9.2 h1:SsGfm7M8QOFtEzumm7UZrZdLLquNdzFYfIbEXntcFbE= -github.com/spf13/cast v1.9.2/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= -github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o= -github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= -github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4= -github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4= -github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA= -github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY= +github.com/sagikazarmark/locafero v0.11.0 h1:1iurJgmM9G3PA/I+wWYIOw/5SyBtxapeHDcg+AAIFXc= +github.com/sagikazarmark/locafero v0.11.0/go.mod h1:nVIGvgyzw595SUSUE6tvCp3YYTeHs15MvlmU87WwIik= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8 h1:+jumHNA0Wrelhe64i8F6HNlS8pkoyMv5sreGx2Ry5Rw= +github.com/sourcegraph/conc v0.3.1-0.20240121214520-5f936abd7ae8/go.mod h1:3n1Cwaq1E1/1lhQhtRK2ts/ZwZEhjcQeJQ1RuC6Q/8U= +github.com/spf13/afero v1.15.0 h1:b/YBCLWAJdFWJTN9cLhiXXcD7mzKn9Dm86dNnfyQw1I= +github.com/spf13/afero v1.15.0/go.mod h1:NC2ByUVxtQs4b3sIUphxK0NioZnmxgyCrfzeuq8lxMg= +github.com/spf13/cast v1.10.0 h1:h2x0u2shc1QuLHfxi+cTJvs30+ZAHOGRic8uyGTDWxY= +github.com/spf13/cast v1.10.0/go.mod h1:jNfB8QC9IA6ZuY2ZjDp0KtFO2LZZlg4S/7bzP6qqeHo= +github.com/spf13/pflag v1.0.10 h1:4EBh2KAYBwaONj6b2Ye1GiHfwjqyROoF4RwYO+vPwFk= +github.com/spf13/pflag v1.0.10/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg= +github.com/spf13/viper v1.21.0 h1:x5S+0EU27Lbphp4UKm1C+1oQO+rKx36vfCoaVebLFSU= +github.com/spf13/viper v1.21.0/go.mod h1:P0lhsswPGWD/1lZJ9ny3fYnVqxiegrlNrEmgLjbTCAY= +github.com/stretchr/testify v1.11.1 h1:7s2iGBzp5EwR7/aIZr8ao5+dra3wiQyKjjFuvgVKu7U= +github.com/stretchr/testify v1.11.1/go.mod h1:wZwfW3scLgRK+23gO65QZefKpKQRnfz6sD981Nm4B6U= github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8= github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= -github.com/urfave/cli/v3 v3.3.8 h1:BzolUExliMdet9NlJ/u4m5vHSotJ3PzEqSAZ1oPMa/E= -github.com/urfave/cli/v3 v3.3.8/go.mod h1:FJSKtM/9AiiTOJL4fJ6TbMUkxBXn7GO9guZqoZtpYpo= +github.com/urfave/cli/v3 v3.6.1 h1:j8Qq8NyUawj/7rTYdBGrxcH7A/j7/G8Q5LhWEW4G3Mo= +github.com/urfave/cli/v3 v3.6.1/go.mod h1:ysVLtOEmg2tOy6PknnYVhDoouyC/6N42TMeoMzskhso= go.uber.org/goleak v1.3.0 h1:2K3zAYmnTNqV73imy9J1T3WC+gmCePx2hEGkimedGto= go.uber.org/goleak v1.3.0/go.mod h1:CoHD4mav9JJNrW/WLlf7HGZPjdw8EucARQHekz1X6bE= go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= -go.uber.org/zap v1.27.0 h1:aJMhYGrd5QSmlpLMr2MftRKl7t8J8PTZPA732ud/XR8= -go.uber.org/zap v1.27.0/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= -golang.org/x/net v0.42.0 h1:jzkYrhi3YQWD6MLBJcsklgQsoAcw89EcZbJw8Z614hs= -golang.org/x/net v0.42.0/go.mod h1:FF1RA5d3u7nAYA4z2TkclSCKh68eSXtiFwcWQpPXdt8= -golang.org/x/sys v0.34.0 h1:H5Y5sJ2L2JRdyv7ROF1he/lPdvFsd0mJHFw2ThKHxLA= -golang.org/x/sys v0.34.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= -golang.org/x/text v0.27.0 h1:4fGWRpyh641NLlecmyl4LOe6yDdfaYNrGb2zdfo4JV4= -golang.org/x/text v0.27.0/go.mod h1:1D28KMCvyooCX9hBiosv5Tz/+YLxj0j7XhWjpSUF7CU= +go.uber.org/zap v1.27.1 h1:08RqriUEv8+ArZRYSTXy1LeBScaMpVSTBhCeaZYfMYc= +go.uber.org/zap v1.27.1/go.mod h1:GB2qFLM7cTU87MWRP2mPIjqfIDnGu+VIO4V/SdhGo2E= +go.yaml.in/yaml/v3 v3.0.4 h1:tfq32ie2Jv2UxXFdLJdh3jXuOzWiL1fo0bu/FbuKpbc= +go.yaml.in/yaml/v3 v3.0.4/go.mod h1:DhzuOOF2ATzADvBadXxruRBLzYTpT36CKvDb3+aBEFg= +go.yaml.in/yaml/v4 v4.0.0-rc.3 h1:3h1fjsh1CTAPjW7q/EMe+C8shx5d8ctzZTrLcs/j8Go= +go.yaml.in/yaml/v4 v4.0.0-rc.3/go.mod h1:aZqd9kCMsGL7AuUv/m/PvWLdg5sjJsZ4oHDEnfPPfY0= +golang.org/x/net v0.48.0 h1:zyQRTTrjc33Lhh0fBgT/H3oZq9WuvRR5gPC70xpDiQU= +golang.org/x/net v0.48.0/go.mod h1:+ndRgGjkh8FGtu1w1FGbEC31if4VrNVMuKTgcAAnQRY= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= -gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= -gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= diff --git a/simapp.go b/simapp.go index 6ff8e76..7a57765 100644 --- a/simapp.go +++ b/simapp.go @@ -19,6 +19,7 @@ import ( "os" "path/filepath" "reflect" + "slices" "strconv" "strings" "time" @@ -29,8 +30,8 @@ import ( "github.com/urfave/cli/v3" "go.uber.org/zap" "go.uber.org/zap/zapcore" + "go.yaml.in/yaml/v4" "golang.org/x/net/http2" - "gopkg.in/yaml.v2" ) type Config struct { @@ -63,11 +64,12 @@ type Configuration struct { } type DevGroup struct { - Name string `yaml:"name,omitempty"` - SiteInfo string `yaml:"site-info,omitempty" json:"site-info,omitempty"` - Imsis []string `yaml:"imsis,omitempty" json:"imsis,omitempty"` - IpDomainName string `yaml:"ip-domain-name,omitempty" json:"ip-domain-name,omitempty"` - IpDomain *IpDomain `yaml:"ip-domain-expanded,omitempty" json:"ip-domain-expanded,omitempty"` + Name string `yaml:"name,omitempty"` + SiteInfo string `yaml:"site-info,omitempty" json:"site-info,omitempty"` + Imsis []string `yaml:"imsis,omitempty" json:"imsis,omitempty"` + Msisdns []string `yaml:"msisdns,omitempty" json:"msisdns,omitempty"` + IpDomainName string `yaml:"ip-domain-name,omitempty" json:"ip-domain-name,omitempty"` + IpDomains []IpDomain `yaml:"ip-domains,omitempty" json:"ip-domains,omitempty"` visited bool } @@ -423,7 +425,7 @@ func sendHttpReqMsg(req *http.Request) (*http.Response, error) { return rsp, nil } nextInterval := getNextBackoffInterval(retries, 2) - logger.SimappLog.Infof("http rsp error [%v], retrying after %d sec", http.StatusText(rsp.StatusCode), nextInterval) + logger.SimappLog.Infof("http rsp error [%s], retrying after %d sec", http.StatusText(rsp.StatusCode), nextInterval) err = rsp.Body.Close() if err != nil { logger.SimappLog.Infoln(err) @@ -446,7 +448,7 @@ func sendMessage(msgChan chan configMessage, subProvisionEndpt SubProvisionEndpt devGroupHttpend = httpProtocol + ip + ":" + subProvisionEndpt.Port + "/config/v1/device-group/" logger.SimappLog.Infoln("device trigger http endpoint", devGroupHttpend) networkSliceHttpend = httpProtocol + ip + ":" + subProvisionEndpt.Port + "/config/v1/network-slice/" - logger.SimappLog.Infoln("network slice http endpoint", devGroupHttpend) + logger.SimappLog.Infoln("network slice http endpoint", networkSliceHttpend) subscriberHttpend = httpProtocol + ip + ":" + subProvisionEndpt.Port + "/api/subscriber/imsi-" logger.SimappLog.Infoln("subscriber http endpoint", subscriberHttpend) baseDestUrl := subscriberHttpend @@ -455,7 +457,7 @@ func sendMessage(msgChan chan configMessage, subProvisionEndpt SubProvisionEndpt devGroupHttpend = httpProtocol + ip + ":" + subProxyEndpt.Port + "/config/v1/device-group/" logger.SimappLog.Infoln("device trigger Proxy http endpoint", devGroupHttpend) networkSliceHttpend = httpProtocol + ip + ":" + subProxyEndpt.Port + "/config/v1/network-slice/" - logger.SimappLog.Infoln("network slice Proxy http endpoint", devGroupHttpend) + logger.SimappLog.Infoln("network slice Proxy http endpoint", networkSliceHttpend) subscriberHttpend = httpProtocol + ip + ":" + subProxyEndpt.Port + "/api/subscriber/imsi-" logger.SimappLog.Infoln("subscriber Proxy http endpoint", subscriberHttpend) } @@ -585,6 +587,13 @@ func compareGroup(groupNew *DevGroup, groupOld *DevGroup) bool { logger.SimappLog.Infoln("number of Imsis changed") return true } + + // Compare MSISDN list length + if !reflect.DeepEqual(groupNew.Msisdns, groupOld.Msisdns) { + logger.SimappLog.Infoln("msisdns list has changed") + return true + } + var allimsiNew string for _, imsi := range groupNew.Imsis { allimsiNew = allimsiNew + imsi @@ -607,27 +616,46 @@ func compareGroup(groupNew *DevGroup, groupOld *DevGroup) bool { if strcode2 != strcode1 { return true } - - oldipdomain := groupOld.IpDomain - newipdomain := groupNew.IpDomain - if oldipdomain.Dnn != newipdomain.Dnn { - return true - } - if oldipdomain.Mtu != newipdomain.Mtu { + if len(groupNew.IpDomains) != len(groupOld.IpDomains) { + logger.SimappLog.Infoln("number of IpDomains changed") return true } - if oldipdomain.UePool != newipdomain.UePool { - return true - } - if oldipdomain.UeDnnQos != nil && newipdomain.UeDnnQos != nil { - if oldipdomain.UeDnnQos.TrafficClass != nil && - newipdomain.UeDnnQos.TrafficClass != nil { - if (oldipdomain.UeDnnQos.TrafficClass.Name != newipdomain.UeDnnQos.TrafficClass.Name) || - (oldipdomain.UeDnnQos.TrafficClass.Qci != newipdomain.UeDnnQos.TrafficClass.Qci) || - (oldipdomain.UeDnnQos.TrafficClass.Arp != newipdomain.UeDnnQos.TrafficClass.Arp) || - (oldipdomain.UeDnnQos.TrafficClass.Pdb != newipdomain.UeDnnQos.TrafficClass.Pdb) || - (oldipdomain.UeDnnQos.TrafficClass.Pelr != newipdomain.UeDnnQos.TrafficClass.Pelr) { - return true + + for i := range groupNew.IpDomains { + if i >= len(groupOld.IpDomains) { + // If groupOld doesn't have enough IpDomains + return true + } + + oldIpDomain := groupOld.IpDomains[i] + newIpDomain := groupNew.IpDomains[i] + + if oldIpDomain.Dnn != newIpDomain.Dnn { + logger.SimappLog.Infoln("DNN changed") + return true + } + + if oldIpDomain.Mtu != newIpDomain.Mtu { + logger.SimappLog.Infoln("MTU changed") + return true + } + + if oldIpDomain.UePool != newIpDomain.UePool { + logger.SimappLog.Infoln("UePool changed") + return true + } + + // Compare UeDnnQos if not nil + if oldIpDomain.UeDnnQos != nil && newIpDomain.UeDnnQos != nil { + if oldIpDomain.UeDnnQos.TrafficClass != nil && newIpDomain.UeDnnQos.TrafficClass != nil { + if oldIpDomain.UeDnnQos.TrafficClass.Name != newIpDomain.UeDnnQos.TrafficClass.Name || + oldIpDomain.UeDnnQos.TrafficClass.Qci != newIpDomain.UeDnnQos.TrafficClass.Qci || + oldIpDomain.UeDnnQos.TrafficClass.Arp != newIpDomain.UeDnnQos.TrafficClass.Arp || + oldIpDomain.UeDnnQos.TrafficClass.Pdb != newIpDomain.UeDnnQos.TrafficClass.Pdb || + oldIpDomain.UeDnnQos.TrafficClass.Pelr != newIpDomain.UeDnnQos.TrafficClass.Pelr { + logger.SimappLog.Infoln("TrafficClass or its properties changed") + return true + } } } } @@ -643,27 +671,13 @@ func compareNetworkSlice(sliceNew *NetworkSlice, sliceOld *NetworkSlice) bool { return true } for _, ng := range sliceNew.DevGroups { - found := false - for _, og := range sliceOld.DevGroups { - if ng == og { - found = true - break - } - } - if !found { + if !slices.Contains(sliceOld.DevGroups, ng) { logger.SimappLog.Infoln("new dev group added in slice") return true // 2 network slices have some difference } } for _, ng := range sliceOld.DevGroups { - found := false - for _, og := range sliceNew.DevGroups { - if ng == og { - found = true - break - } - } - if !found { + if !slices.Contains(sliceNew.DevGroups, ng) { logger.SimappLog.Infoln("dev group deleted in slice") return true // 2 network slices have some difference } @@ -682,14 +696,9 @@ func compareNetworkSlice(sliceNew *NetworkSlice, sliceOld *NetworkSlice) bool { } for _, newgnb := range newSite.Gnb { - found := false - for _, oldgnb := range oldSite.Gnb { - if newgnb.Name == oldgnb.Name && newgnb.Tac == oldgnb.Tac { - found = true - break - } - } - if !found { + if !slices.ContainsFunc(oldSite.Gnb, func(oldgnb *Gnb) bool { + return newgnb.Name == oldgnb.Name && newgnb.Tac == oldgnb.Tac + }) { logger.SimappLog.Infoln("gnb changed in slice") return true // change in slice details } @@ -699,6 +708,25 @@ func compareNetworkSlice(sliceNew *NetworkSlice, sliceOld *NetworkSlice) bool { return false } +func isImsiInSubscribers(imsi int, subscribers []*Subscriber) (bool, *Subscriber) { + for _, subscriber := range subscribers { + start, err := strconv.Atoi(subscriber.UeIdStart) + if err != nil { + logger.SimappLog.Errorln("error in Atoi with UeIdStart", err) + continue + } + end, err := strconv.Atoi(subscriber.UeIdEnd) + if err != nil { + logger.SimappLog.Errorln("error in Atoi with UeIdEnd", err) + continue + } + if imsi >= start && imsi <= end { + return true, subscriber + } + } + return false, nil +} + func UpdateConfig(f string) error { if content, err := os.ReadFile(f); err != nil { return err @@ -715,8 +743,7 @@ func UpdateConfig(f string) error { logger.SimappLog.Infoln("number of subscriber ranges in updated config", len(SimappConfig.Configuration.Subscriber)) var newImsiList []uint64 - for o := 0; o < len(NewSimappConfig.Configuration.Subscriber); o++ { - newSubscribers := NewSimappConfig.Configuration.Subscriber[o] + for _, newSubscribers := range NewSimappConfig.Configuration.Subscriber { logger.SimappLog.Infoln("Subscribers:") logger.SimappLog.Infoln("UeIdStart", newSubscribers.UeIdStart) logger.SimappLog.Infoln("UeIdEnd", newSubscribers.UeIdEnd) @@ -737,31 +764,13 @@ func UpdateConfig(f string) error { continue } for i := newStart; i <= newEnd; i++ { - found := false newImsiList = append(newImsiList, uint64(i)) - for s := 0; s < len(SimappConfig.Configuration.Subscriber); s++ { - subscribers := SimappConfig.Configuration.Subscriber[s] - start, err := strconv.Atoi(subscribers.UeIdStart) - if err != nil { - logger.SimappLog.Errorln("error in Atoi with UeIdStart", err) - continue - } - end, err := strconv.Atoi(subscribers.UeIdEnd) - if err != nil { - logger.SimappLog.Errorln("error in Atoi with UeIdEnd", err) - continue - } - for j := start; j <= end; j++ { - if i == j { // two subcribers' imsi are same - found = true - if compareSubscriber(newSubscribers, subscribers) { - logger.SimappLog.Warnln("subscriber provision not support modify yet") - } - break - } - } - } + + found, existingSubscriber := isImsiInSubscribers(i, SimappConfig.Configuration.Subscriber) if found { + if compareSubscriber(newSubscribers, existingSubscriber) { + logger.SimappLog.Warnln("subscriber provision not support modify yet") + } continue } // add subscriber to chan @@ -782,8 +791,7 @@ func UpdateConfig(f string) error { } } // delete all the existing subscribers not show up in new config. - for o := 0; o < len(SimappConfig.Configuration.Subscriber); o++ { - subscribers := SimappConfig.Configuration.Subscriber[o] + for _, subscribers := range SimappConfig.Configuration.Subscriber { start, err := strconv.Atoi(subscribers.UeIdStart) if err != nil { logger.SimappLog.Errorln("error in Atoi with UeIdStart", err) @@ -795,13 +803,7 @@ func UpdateConfig(f string) error { continue } for k := start; k <= end; k++ { - has := false - for _, v := range newImsiList { - if v == uint64(k) { - has = true - } - } - if !has { + if !slices.Contains(newImsiList, uint64(k)) { logger.SimappLog.Infoln("going to delete subscriber:", k) b, err := json.Marshal("") if err != nil { @@ -835,11 +837,8 @@ func UpdateConfig(f string) error { dispatchGroup(configMsgChan, groupNew, modify_op) // find all slices which are using this device group and mark them modified for _, slice := range SimappConfig.Configuration.NetworkSlice { - for _, dg := range slice.DevGroups { - if groupOld.Name == dg { - slice.modified = true - break - } + if slices.Contains(slice.DevGroups, groupOld.Name) { + slice.modified = true } } } else { @@ -863,11 +862,8 @@ func UpdateConfig(f string) error { dispatchGroup(configMsgChan, group, delete_op) // find all slices which are using this device group and mark them modified for _, slice := range SimappConfig.Configuration.NetworkSlice { - for _, dg := range slice.DevGroups { - if group.Name == dg { - slice.modified = true - break - } + if slices.Contains(slice.DevGroups, group.Name) { + slice.modified = true } } } @@ -924,7 +920,7 @@ func WatchConfig() { viper.OnConfigChange(func(e fsnotify.Event) { logger.SimappLog.Infoln("config file changed:", e.Name) if err := UpdateConfig("config/simapp.yaml"); err != nil { - logger.SimappLog.Errorln("error in loading updated configuration ", err) + logger.SimappLog.Errorln("error in loading updated configuration", err) } else { logger.SimappLog.Infoln("successfully updated configuration") } @@ -934,9 +930,10 @@ func WatchConfig() { func dispatchAllSubscribers(configMsgChan chan configMessage) { logger.SimappLog.Infoln("number of subscriber ranges", len(SimappConfig.Configuration.Subscriber)) - for o := 0; o < len(SimappConfig.Configuration.Subscriber); o++ { - subscribers := SimappConfig.Configuration.Subscriber[o] - logger.SimappLog.Infof("Subscribers: UeIdStart: %s, UeIdEnd: %s, PlmnId: %s, OPc: %s, OP: %s, Key: %s, SequenceNumber: %s", subscribers.UeIdStart, subscribers.UeIdEnd, subscribers.PlmnId, subscribers.OPc, subscribers.OP, subscribers.Key, subscribers.SequenceNumber) + for _, subscribers := range SimappConfig.Configuration.Subscriber { + logger.SimappLog.Infof("subscribers: UeIdStart: %s, UeIdEnd: %s, PlmnId: %s, OPc: %s, OP: %s, Key: %s, SequenceNumber: %s", + subscribers.UeIdStart, subscribers.UeIdEnd, subscribers.PlmnId, subscribers.OPc, + subscribers.OP, subscribers.Key, subscribers.SequenceNumber) start, err := strconv.Atoi(subscribers.UeIdStart) if err != nil { logger.SimappLog.Errorln("error in Atoi with UeIdStart", err) @@ -974,16 +971,26 @@ func dispatchGroup(configMsgChan chan configMessage, group *DevGroup, msgOp int) logger.SimappLog.Infoln("group name", group.Name) logger.SimappLog.Infoln("site name", group.SiteInfo) logger.SimappLog.Infoln("imsis", group.Imsis) - for im := 0; im < len(group.Imsis); im++ { - logger.SimappLog.Debugln("imsi", group.Imsis[im]) + for _, imsi := range group.Imsis { + logger.SimappLog.Debugln("imsi", imsi) } logger.SimappLog.Infoln("IpDomainName", group.IpDomainName) - ipDomain := group.IpDomain - if group.IpDomain != nil { - logger.SimappLog.Infoln("IpDomain Dnn", ipDomain.Dnn) - logger.SimappLog.Infoln("IpDomain Dns Primary", ipDomain.DnsPrimary) - logger.SimappLog.Infoln("IpDomain Mtu", ipDomain.Mtu) - logger.SimappLog.Infoln("IpDomain UePool", ipDomain.UePool) + if group.IpDomains != nil { + for _, ipDomain := range group.IpDomains { + logger.SimappLog.Infoln(" IpDomain Dnn:", ipDomain.Dnn) + logger.SimappLog.Infoln(" IpDomain Dns Primary:", ipDomain.DnsPrimary) + logger.SimappLog.Infoln(" IpDomain Mtu:", ipDomain.Mtu) + logger.SimappLog.Infoln(" IpDomain UePool:", ipDomain.UePool) + + // Check for UeDnnQos field if it's populated + if ipDomain.UeDnnQos != nil { + logger.SimappLog.Infoln(" UeDnnQos:", ipDomain.UeDnnQos) + } else { + logger.SimappLog.Warnln(" UeDnnQos is nil") + } + } + } else { + logger.SimappLog.Warnln(" IpDomains is nil") } b, err := json.Marshal(group) if err != nil { @@ -991,6 +998,10 @@ func dispatchGroup(configMsgChan chan configMessage, group *DevGroup, msgOp int) return } reqMsgBody := bytes.NewBuffer(b) + if !SimappConfig.Configuration.ConfigSliceDevGroup { + logger.SimappLog.Warnln("Do not configure network slice") + return + } var msg configMessage msg.msgPtr = reqMsgBody msg.msgType = device_group @@ -1011,21 +1022,21 @@ func dispatchNetworkSlice(configMsgChan chan configMessage, slice *NetworkSlice, logger.SimappLog.Warnln("do not configure network slice") return } - logger.SimappLog.Infoln("slice Name:", slice.Name) + logger.SimappLog.Infoln("slice name:", slice.Name) logger.SimappLog.Infof("slice sst %v, sd %v", slice.SliceId.Sst, slice.SliceId.Sd) - logger.SimappLog.Infoln("slice site info", slice.SiteInfo) + logger.SimappLog.Infof("slice site info: %+v", slice.SiteInfo) site := slice.SiteInfo logger.SimappLog.Infoln("slice site name", site.SiteName) logger.SimappLog.Infoln("slice gNB", len(site.Gnb)) - for e := 0; e < len(site.Gnb); e++ { - logger.SimappLog.Infof("slice gNB[%v] = %s, tac: %d", e, site.Gnb[e].Name, site.Gnb[e].Tac) + for i, gnb := range site.Gnb { + logger.SimappLog.Infof("slice gNB[%v] = %s, tac: %d", i, gnb.Name, gnb.Tac) } - logger.SimappLog.Infoln("slice Plmn", site.Plmn) - logger.SimappLog.Infoln("slice Upf", site.Upf) + logger.SimappLog.Infof("slice Plmn %+v", site.Plmn) + logger.SimappLog.Infof("slice Upf %+v", site.Upf) logger.SimappLog.Infoln("slice device groups", slice.DevGroups) - for im := 0; im < len(slice.DevGroups); im++ { - logger.SimappLog.Infoln("attached device groups", slice.DevGroups[im]) + for _, devGroup := range slice.DevGroups { + logger.SimappLog.Infoln("attached device group", devGroup) } b, err := json.Marshal(slice)