Skip to content

Commit

Permalink
Reduce permissions required by the Import Resources PipelineRun
Browse files Browse the repository at this point in the history
Update the PipelineRun to work as expected with the latest v1beta1
and v1 PipelineRun resource, the `spec.serviceAccountName` field
has been removed.

Create a new `tekton-dashboard` namespace that will be the default
namespace used for the PipelineRun, and update the tutorial to
reference this and create the required RoleBinding.
  • Loading branch information
AlanGreene authored and tekton-robot committed Apr 6, 2023
1 parent 70c7397 commit 7c14b1a
Show file tree
Hide file tree
Showing 8 changed files with 83 additions and 30 deletions.
8 changes: 3 additions & 5 deletions docs/tutorial.md
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,7 @@ You can now open the Dashboard in your browser at http://localhost:9097

The import must be executed using a ServiceAccount with permissions to create the resources being imported.

For this tutorial we will create a ClusterRole granting permission to create a number of Tekton resources, and a RoleBinding configuring this for the `default` ServiceAccount in the `default` namespace.
For this tutorial we will create a ClusterRole granting permission to create a number of Tekton resources, and a RoleBinding configuring this so that the `default` ServiceAccount in the `tekton-dashboard` namespace can create resources in the `default` namespace.

```bash
kubectl apply -f - <<EOF
Expand Down Expand Up @@ -155,7 +155,7 @@ roleRef:
subjects:
- kind: ServiceAccount
name: default
namespace: default
namespace: tekton-dashboard
EOF
```

Expand All @@ -168,9 +168,7 @@ We will import [two simple Tasks and a Pipeline definition](https://github.com/t
- Repository URL: `https://github.com/tektoncd/dashboard`
- Repository path: `docs/tutorial`
- Target namespace: `default`
1. Expand the 'Advanced configuration' section and fill in the following:
- Namespace: `default`
- Service Account: `default`
- If selecting a different value, ensure the selected ServiceAccount has permission to create resources in this namespace
1. Leave the default values for the rest of the fields
1. Click the `Import and Apply` button

Expand Down
21 changes: 21 additions & 0 deletions overlays/installer/read-write/100-namespace.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
# Copyright 2023 The Tekton Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

apiVersion: v1
kind: Namespace
metadata:
name: tekton-dashboard
labels:
app.kubernetes.io/instance: default
app.kubernetes.io/part-of: tekton-dashboard
3 changes: 2 additions & 1 deletion overlays/installer/read-write/kustomization.yaml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Copyright 2020 The Tekton Authors
# Copyright 2020-2023 The Tekton Authors
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
Expand All @@ -17,6 +17,7 @@ apiVersion: kustomize.config.k8s.io/v1beta1
kind: Kustomization
resources:
- ../base
- 100-namespace.yaml
patchesJson6902:
- target:
group: rbac.authorization.k8s.io
Expand Down
24 changes: 21 additions & 3 deletions src/api/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -221,8 +221,9 @@ export function importResources({
serviceAccount
}) {
const pipelineRun = deepClone(importResourcesPipelineRunTemplate);
const pipelinesAPIVersion = getTektonPipelinesAPIVersion();

pipelineRun.apiVersion = `tekton.dev/${getTektonPipelinesAPIVersion()}`;
pipelineRun.apiVersion = `tekton.dev/${pipelinesAPIVersion}`;
pipelineRun.metadata.name = `import-resources-${Date.now()}`;
pipelineRun.metadata.labels = {
...labels,
Expand All @@ -237,12 +238,29 @@ export function importResources({
];

if (serviceAccount) {
pipelineRun.spec.serviceAccountName = serviceAccount;
if (pipelinesAPIVersion === 'v1') {
pipelineRun.spec.taskRunTemplate = {
podTemplate: { ...pipelineRun.spec.podTemplate },
serviceAccountName: serviceAccount
};
delete pipelineRun.spec.podTemplate;
} else {
pipelineRun.spec.taskRunSpecs = [
{
pipelineTaskName: 'fetch-repo',
taskServiceAccountName: serviceAccount
},
{
pipelineTaskName: 'import-resources',
taskServiceAccountName: serviceAccount
}
];
}
}

const uri = getTektonAPI('pipelineruns', {
namespace: importerNamespace,
version: getTektonPipelinesAPIVersion()
version: pipelinesAPIVersion
});
return post(uri, pipelineRun).then(({ body }) => body);
}
Expand Down
11 changes: 10 additions & 1 deletion src/api/index.test.js
Original file line number Diff line number Diff line change
Expand Up @@ -305,7 +305,16 @@ describe('importResources', () => {
{ name: 'revision', value: undefined },
{ name: 'target-namespace', value: namespace }
]),
serviceAccountName: serviceAccount
taskRunSpecs: [
{
pipelineTaskName: 'fetch-repo',
taskServiceAccountName: serviceAccount
},
{
pipelineTaskName: 'import-resources',
taskServiceAccountName: serviceAccount
}
]
})
})
);
Expand Down
18 changes: 16 additions & 2 deletions src/api/resources/import-resources-pipelinerun.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,13 @@ metadata:
# additional labels will be added in the API layer
dashboard.tekton.dev/import: 'true'
spec:
podTemplate:
securityContext:
runAsUser: 65532
runAsGroup: 65532
runAsNonRoot: true
seccompProfile:
type: RuntimeDefault
pipelineSpec:
params:
- name: method
Expand Down Expand Up @@ -66,8 +73,10 @@ spec:
- name: WORKSPACE_PATH
value: $(workspaces.repo.path)
securityContext:
runAsNonRoot: true
runAsUser: 65532
allowPrivilegeEscalation: false
capabilities:
drop:
- "ALL"
script: |
#!/usr/bin/env sh
set -eu
Expand Down Expand Up @@ -102,6 +111,11 @@ spec:
steps:
- name: import
image: lachlanevenson/k8s-kubectl:latest
securityContext:
allowPrivilegeEscalation: false
capabilities:
drop:
- "ALL"
command: ['kubectl']
args: [
'$(params.method)',
Expand Down
11 changes: 3 additions & 8 deletions src/containers/ImportResources/ImportResources.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2019-2022 The Tekton Authors
Copyright 2019-2023 The Tekton Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
Expand Down Expand Up @@ -34,11 +34,7 @@ import {
useTitleSync
} from '@tektoncd/dashboard-utils';
import parseGitURL from 'git-url-parse';
import {
importResources,
useDashboardNamespace,
useSelectedNamespace
} from '../../api';
import { importResources, useSelectedNamespace } from '../../api';
import { NamespacesDropdown, ServiceAccountsDropdown } from '..';

const itemToString = ({ text }) => text;
Expand Down Expand Up @@ -66,10 +62,9 @@ const HelpIcon = ({ title }) => (
export function ImportResources() {
const intl = useIntl();
const { selectedNamespace: navNamespace } = useSelectedNamespace();
const dashboardNamespace = useDashboardNamespace();

const [importerNamespace, setImporterNamespace] =
useState(dashboardNamespace);
useState('tekton-dashboard');
const [invalidImporterNamespace, setInvalidImporterNamespace] =
useState(false);
const [invalidInput, setInvalidInput] = useState(false);
Expand Down
17 changes: 7 additions & 10 deletions src/containers/ImportResources/ImportResources.test.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
Copyright 2019-2021 The Tekton Authors
Copyright 2019-2023 The Tekton Authors
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
Expand All @@ -22,13 +22,10 @@ import * as APIUtils from '../../api/utils';

describe('ImportResources component', () => {
beforeEach(() => {
jest
.spyOn(API, 'useDashboardNamespace')
.mockImplementation(() => 'namespace1');
jest.spyOn(API, 'useNamespaces').mockImplementation(() => ({
data: [
{ metadata: { name: 'namespace1' } },
{ metadata: { name: 'default' } }
{ metadata: { name: 'default' } },
{ metadata: { name: 'tekton-dashboard' } }
]
}));
jest
Expand Down Expand Up @@ -71,7 +68,7 @@ describe('ImportResources component', () => {
await waitFor(() => getByText(/Please select a Namespace/i));
});

it('Valid data submit displays success notification ', async () => {
it('Valid data submit displays success notification', async () => {
const pipelineRunName = 'fake-tekton-pipeline-run';
const headers = {
metadata: { name: pipelineRunName }
Expand Down Expand Up @@ -105,7 +102,7 @@ describe('ImportResources component', () => {
expect(namespace).toEqual('default');
expect(labels).toEqual(labelsShouldEqual);
expect(serviceAccount).toEqual('');
expect(importerNamespace).toEqual('namespace1');
expect(importerNamespace).toEqual('tekton-dashboard');

return Promise.resolve(headers);
}
Expand Down Expand Up @@ -138,7 +135,7 @@ describe('ImportResources component', () => {
.innerHTML
).toContain(
urls.pipelineRuns.byName({
namespace: 'namespace1',
namespace: 'tekton-dashboard',
pipelineRunName
})
);
Expand All @@ -158,7 +155,7 @@ describe('ImportResources component', () => {
fireEvent.change(repoURLField, { target: { value: 'URL' } });

fireEvent.click(getAllByPlaceholderText(/select namespace/i)[0]);
fireEvent.click(getByText('namespace1'));
fireEvent.click(getByText('tekton-dashboard'));

fireEvent.click(getByText('Import'));
await waitFor(() => getByText(/Please enter a valid Git URL/i));
Expand Down

0 comments on commit 7c14b1a

Please sign in to comment.