summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/cleanup-mirror-pr-branch.yml35
-rw-r--r--.github/workflows/repo-sync.yml18
-rw-r--r--.github/workflows/trigger-pr-mirror-repo-sync.yml38
-rw-r--r--.github/workflows/trigger-pr.yml19
-rw-r--r--data/templates/accel-ppp/chap-secrets.ipoe.j22
-rw-r--r--data/templates/frr/static_routes_macro.j210
-rw-r--r--interface-definitions/include/static/static-route.xml.i2
-rw-r--r--interface-definitions/service_ipoe-server.xml.in12
-rwxr-xr-xsmoketest/scripts/cli/test_service_ipoe-server.py35
9 files changed, 128 insertions, 43 deletions
diff --git a/.github/workflows/cleanup-mirror-pr-branch.yml b/.github/workflows/cleanup-mirror-pr-branch.yml
new file mode 100644
index 000000000..c5de9ab73
--- /dev/null
+++ b/.github/workflows/cleanup-mirror-pr-branch.yml
@@ -0,0 +1,35 @@
+name: Cleanup pr mirror branch
+
+on:
+ pull_request:
+ types: [closed]
+ branches:
+ - current
+ workflow_dispatch:
+ inputs:
+ branch:
+ description: 'Branch to delete'
+ required: true
+
+permissions:
+ contents: write
+
+jobs:
+ delete_branch:
+ if: ${{ (github.event_name == 'workflow_dispatch' || startsWith(github.event.pull_request.head.ref, 'mirror/')) && github.repository_owner != 'vyos' }}
+ runs-on: ubuntu-latest
+
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+
+ - name: Delete branch
+ run: |
+ branch=${{ github.event_name == 'workflow_dispatch' && github.event.inputs.branch || github.event.pull_request.head.ref }}
+ if [[ $branch != mirror/* ]]; then
+ echo "Branch name to clean must start with 'mirror/'"
+ exit 1
+ fi
+ repo=${{ github.repository }}
+ git remote set-url origin https://x-access-token:${{ secrets.GITHUB_TOKEN }}@github.com/${{ github.repository }}
+ git push origin --delete $branch
diff --git a/.github/workflows/repo-sync.yml b/.github/workflows/repo-sync.yml
deleted file mode 100644
index 752cf947a..000000000
--- a/.github/workflows/repo-sync.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-name: Repo-sync
-
-on:
- pull_request_target:
- types:
- - closed
- branches:
- - current
- - equuleus
- workflow_dispatch:
-
-jobs:
- trigger-sync:
- uses: vyos/.github/.github/workflows/trigger-repo-sync.yml@current
- secrets:
- REMOTE_REPO: ${{ secrets.REMOTE_REPO }}
- REMOTE_OWNER: ${{ secrets.REMOTE_OWNER }}
- PAT: ${{ secrets.PAT }}
diff --git a/.github/workflows/trigger-pr-mirror-repo-sync.yml b/.github/workflows/trigger-pr-mirror-repo-sync.yml
new file mode 100644
index 000000000..9653c2dca
--- /dev/null
+++ b/.github/workflows/trigger-pr-mirror-repo-sync.yml
@@ -0,0 +1,38 @@
+name: Trigger Mirror PR and Repo Sync
+on:
+ pull_request_target:
+ types:
+ - closed
+ branches:
+ - current
+
+env:
+ GH_TOKEN: ${{ secrets.PAT }}
+
+concurrency:
+ group: trigger-pr-mirror-repo-sync-${{ github.event.pull_request.base.ref }}
+ cancel-in-progress: false
+jobs:
+ trigger-mirror-pr-repo-sync:
+ if: ${{ github.repository_owner == 'vyos' }}
+ runs-on: ubuntu-latest
+ permissions:
+ pull-requests: write
+ contents: write
+
+ steps:
+ - name: Bullfrog Secure Runner
+ uses: bullfrogsec/bullfrog@v0
+ with:
+ egress-policy: audit
+
+ - name: Trigger repo sync
+ shell: bash
+ run: |
+ echo "Triggering sync workflow for ${{ secrets.REMOTE_OWNER }}/${{ secrets.REMOTE_REPO }}"
+ echo "Triggering sync workflow with PAT ${{ secrets.PAT }}"
+ curl -X POST \
+ -H "Accept: application/vnd.github.everest-preview+json" \
+ -H "Authorization: Bearer ${{ secrets.PAT }}" \
+ https://api.github.com/repos/${{ secrets.REMOTE_OWNER }}/${{ secrets.REMOTE_REPO }}/actions/workflows/mirror-pr-and-sync.yml/dispatches \
+ -d '{"ref":"git-actions", "inputs": {"pr_number": "${{ github.event.pull_request.number }}", "sync_branch": "${{ github.event.pull_request.base.ref }}"}}'
diff --git a/.github/workflows/trigger-pr.yml b/.github/workflows/trigger-pr.yml
deleted file mode 100644
index f88458a81..000000000
--- a/.github/workflows/trigger-pr.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-name: Trigger PR
-
-on:
- pull_request_target:
- types:
- - closed
- branches:
- - circinus
-
-jobs:
- trigger-PR:
- uses: vyos/.github/.github/workflows/trigger-pr.yml@current
- with:
- source_branch: 'circinus'
- target_branch: 'circinus'
- secrets:
- REMOTE_REPO: ${{ secrets.REMOTE_REPO }}
- REMOTE_OWNER: ${{ secrets.REMOTE_OWNER }}
- PAT: ${{ secrets.PAT }}
diff --git a/data/templates/accel-ppp/chap-secrets.ipoe.j2 b/data/templates/accel-ppp/chap-secrets.ipoe.j2
index 43083e22e..dd85160c0 100644
--- a/data/templates/accel-ppp/chap-secrets.ipoe.j2
+++ b/data/templates/accel-ppp/chap-secrets.ipoe.j2
@@ -6,7 +6,7 @@
{% if mac_config.vlan is vyos_defined %}
{% set iface = iface ~ '.' ~ mac_config.vlan %}
{% endif %}
-{{ "%-11s" | format(iface) }} * {{ mac | lower }} * {{ mac_config.rate_limit.download ~ '/' ~ mac_config.rate_limit.upload if mac_config.rate_limit.download is vyos_defined and mac_config.rate_limit.upload is vyos_defined }}
+{{ "%-11s" | format(iface) }} * {{ mac | lower }} {{ mac_config.static_ip if mac_config.static_ip is vyos_defined else '*' }} {{ mac_config.rate_limit.download ~ '/' ~ mac_config.rate_limit.upload if mac_config.rate_limit.download is vyos_defined and mac_config.rate_limit.upload is vyos_defined }}
{% endfor %}
{% endif %}
{% endfor %}
diff --git a/data/templates/frr/static_routes_macro.j2 b/data/templates/frr/static_routes_macro.j2
index cf8046968..db31700c5 100644
--- a/data/templates/frr/static_routes_macro.j2
+++ b/data/templates/frr/static_routes_macro.j2
@@ -6,10 +6,12 @@
{{ ip_ipv6 }} route {{ prefix }} reject {{ prefix_config.reject.distance if prefix_config.reject.distance is vyos_defined }} {{ 'tag ' ~ prefix_config.reject.tag if prefix_config.reject.tag is vyos_defined }} {{ 'table ' ~ table if table is vyos_defined }}
{% endif %}
{% if prefix_config.dhcp_interface is vyos_defined %}
-{% set next_hop = prefix_config.dhcp_interface | get_dhcp_router %}
-{% if next_hop is vyos_defined %}
-{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ prefix_config.dhcp_interface }} {{ 'table ' ~ table if table is vyos_defined }}
-{% endif %}
+{% for dhcp_interface in prefix_config.dhcp_interface %}
+{% set next_hop = dhcp_interface | get_dhcp_router %}
+{% if next_hop is vyos_defined %}
+{{ ip_ipv6 }} route {{ prefix }} {{ next_hop }} {{ dhcp_interface }} {{ 'table ' ~ table if table is vyos_defined }}
+{% endif %}
+{% endfor %}
{% endif %}
{% if prefix_config.interface is vyos_defined %}
{% for interface, interface_config in prefix_config.interface.items() if interface_config.disable is not defined %}
diff --git a/interface-definitions/include/static/static-route.xml.i b/interface-definitions/include/static/static-route.xml.i
index 29921a731..51e45c6f7 100644
--- a/interface-definitions/include/static/static-route.xml.i
+++ b/interface-definitions/include/static/static-route.xml.i
@@ -13,7 +13,7 @@
<children>
#include <include/static/static-route-blackhole.xml.i>
#include <include/static/static-route-reject.xml.i>
- #include <include/dhcp-interface.xml.i>
+ #include <include/dhcp-interface-multi.xml.i>
#include <include/generic-description.xml.i>
<tagNode name="interface">
<properties>
diff --git a/interface-definitions/service_ipoe-server.xml.in b/interface-definitions/service_ipoe-server.xml.in
index 39cfb7889..6cc4471af 100644
--- a/interface-definitions/service_ipoe-server.xml.in
+++ b/interface-definitions/service_ipoe-server.xml.in
@@ -70,6 +70,18 @@
<constraintErrorMessage>VLAN IDs need to be in range 1-4094</constraintErrorMessage>
</properties>
</leafNode>
+ <leafNode name="static-ip">
+ <properties>
+ <help>Static client IP address</help>
+ <valueHelp>
+ <format>ipv4</format>
+ <description>IPv4 address</description>
+ </valueHelp>
+ <constraint>
+ <validator name="ipv4-address"/>
+ </constraint>
+ </properties>
+ </leafNode>
</children>
</tagNode>
</children>
diff --git a/smoketest/scripts/cli/test_service_ipoe-server.py b/smoketest/scripts/cli/test_service_ipoe-server.py
index be03179bf..ab0898d17 100755
--- a/smoketest/scripts/cli/test_service_ipoe-server.py
+++ b/smoketest/scripts/cli/test_service_ipoe-server.py
@@ -260,6 +260,41 @@ delegate={delegate_2_prefix},{delegate_mask},name={pool_name}"""
tmp = ','.join(vlans)
self.assertIn(f'{interface},{tmp}', conf['ipoe']['vlan-mon'])
+ def test_ipoe_server_static_client_ip(self):
+ mac_address = '08:00:27:2f:d8:06'
+ ip_address = '192.0.2.100'
+
+ # Test configuration of local authentication for PPPoE server
+ self.basic_config()
+ # Rewrite authentication from basic_config
+ self.set(
+ [
+ 'authentication',
+ 'interface',
+ interface,
+ 'mac',
+ mac_address,
+ 'static-ip',
+ ip_address,
+ ]
+ )
+ self.set(['authentication', 'mode', 'local'])
+ # commit changes
+ self.cli_commit()
+
+ # Validate configuration values
+ conf = ConfigParser(allow_no_value=True, delimiters='=', strict=False)
+ conf.read(self._config_file)
+
+ # basic verification
+ self.verify(conf)
+
+ # check local users
+ tmp = cmd(f'sudo cat {self._chap_secrets}')
+ regex = f'{interface}\s+\*\s+{mac_address}\s+{ip_address}'
+ tmp = re.findall(regex, tmp)
+ self.assertTrue(tmp)
+
@unittest.skip("PPP is not a part of IPoE")
def test_accel_ppp_options(self):
pass