Skip to content

Commit 858e619

Browse files
author
Jeff Peeler
committed
test(e2e): add operator group SA permission tests
The first test ensures that a service account with insufficient permissions is properly handled after necessary RBAC is added to the service account. The second test ensures that an operator group with a service account that is lacking permissions then properly installs a CSV after the limiting service account is removed from the spec.
1 parent 3f352d7 commit 858e619

File tree

1 file changed

+237
-0
lines changed

1 file changed

+237
-0
lines changed

test/e2e/operator_groups_e2e_test.go

Lines changed: 237 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1613,3 +1613,240 @@ func TestCSVCopyWatchingAllNamespaces(t *testing.T) {
16131613
})
16141614
require.NoError(t, err)
16151615
}
1616+
1617+
func TestOperatorGroupInsufficientPermissionsResolveViaRBAC(t *testing.T) {
1618+
defer cleaner.NotifyTestComplete(t, true)
1619+
1620+
log := func(s string) {
1621+
t.Logf("%s: %s", time.Now().Format("15:04:05.9999"), s)
1622+
}
1623+
1624+
c := newKubeClient(t)
1625+
crc := newCRClient(t)
1626+
csvName := genName("another-csv-")
1627+
1628+
newNamespaceName := genName(testNamespace + "-")
1629+
1630+
_, err := c.KubernetesInterface().CoreV1().Namespaces().Create(&corev1.Namespace{
1631+
ObjectMeta: metav1.ObjectMeta{
1632+
Name: newNamespaceName,
1633+
},
1634+
})
1635+
require.NoError(t, err)
1636+
defer func() {
1637+
err = c.KubernetesInterface().CoreV1().Namespaces().Delete(newNamespaceName, &metav1.DeleteOptions{})
1638+
require.NoError(t, err)
1639+
}()
1640+
1641+
log("Creating CRD")
1642+
mainCRDPlural := genName("opgroup")
1643+
mainCRD := newCRD(mainCRDPlural)
1644+
cleanupCRD, err := createCRD(c, mainCRD)
1645+
require.NoError(t, err)
1646+
defer cleanupCRD()
1647+
1648+
log("Creating operator group")
1649+
serviceAccountName := genName("nginx-sa")
1650+
// intentionally creating an operator group without a service account already existing
1651+
operatorGroup := v1.OperatorGroup{
1652+
ObjectMeta: metav1.ObjectMeta{
1653+
Name: genName("e2e-operator-group-"),
1654+
Namespace: newNamespaceName,
1655+
},
1656+
Spec: v1.OperatorGroupSpec{
1657+
ServiceAccountName: serviceAccountName,
1658+
TargetNamespaces: []string{newNamespaceName},
1659+
},
1660+
}
1661+
_, err = crc.OperatorsV1().OperatorGroups(newNamespaceName).Create(&operatorGroup)
1662+
require.NoError(t, err)
1663+
1664+
log("Creating CSV")
1665+
1666+
// Create a new NamedInstallStrategy
1667+
deploymentName := genName("operator-deployment")
1668+
namedStrategy := newNginxInstallStrategy(deploymentName, nil, nil)
1669+
1670+
aCSV := newCSV(csvName, newNamespaceName, "", semver.MustParse("0.0.0"), []apiextensions.CustomResourceDefinition{mainCRD}, nil, namedStrategy)
1671+
createdCSV, err := crc.OperatorsV1alpha1().ClusterServiceVersions(newNamespaceName).Create(&aCSV)
1672+
require.NoError(t, err)
1673+
1674+
serviceAccount := &corev1.ServiceAccount{
1675+
ObjectMeta: metav1.ObjectMeta{
1676+
Namespace: newNamespaceName,
1677+
Name: serviceAccountName,
1678+
},
1679+
}
1680+
ownerutil.AddNonBlockingOwner(serviceAccount, createdCSV)
1681+
err = ownerutil.AddOwnerLabels(serviceAccount, createdCSV)
1682+
require.NoError(t, err)
1683+
1684+
_, err = c.CreateServiceAccount(serviceAccount)
1685+
require.NoError(t, err)
1686+
1687+
log("wait for CSV to fail")
1688+
err = wait.Poll(pollInterval, pollDuration, func() (bool, error) {
1689+
fetched, err := crc.OperatorsV1alpha1().ClusterServiceVersions(newNamespaceName).Get(createdCSV.GetName(), metav1.GetOptions{})
1690+
if err != nil {
1691+
return false, err
1692+
}
1693+
log(fmt.Sprintf("%s (%s): %s", fetched.Status.Phase, fetched.Status.Reason, fetched.Status.Message))
1694+
return csvFailedChecker(fetched), nil
1695+
})
1696+
require.NoError(t, err)
1697+
1698+
// now add cluster admin permissions to service account
1699+
role := &rbacv1.Role{
1700+
ObjectMeta: metav1.ObjectMeta{
1701+
Namespace: newNamespaceName,
1702+
Name: serviceAccountName + "-role",
1703+
},
1704+
Rules: []rbacv1.PolicyRule{
1705+
{
1706+
Verbs: []string{"*"},
1707+
APIGroups: []string{"*"},
1708+
Resources: []string{"*"},
1709+
},
1710+
},
1711+
}
1712+
ownerutil.AddNonBlockingOwner(role, createdCSV)
1713+
err = ownerutil.AddOwnerLabels(role, createdCSV)
1714+
require.NoError(t, err)
1715+
1716+
roleBinding := &rbacv1.RoleBinding{
1717+
ObjectMeta: metav1.ObjectMeta{
1718+
Namespace: newNamespaceName,
1719+
Name: serviceAccountName + "-rb",
1720+
},
1721+
Subjects: []rbacv1.Subject{
1722+
{
1723+
Kind: "ServiceAccount",
1724+
Name: serviceAccountName,
1725+
Namespace: newNamespaceName,
1726+
},
1727+
},
1728+
RoleRef: rbacv1.RoleRef{
1729+
Kind: "Role",
1730+
Name: role.GetName(),
1731+
},
1732+
}
1733+
ownerutil.AddNonBlockingOwner(roleBinding, createdCSV)
1734+
err = ownerutil.AddOwnerLabels(roleBinding, createdCSV)
1735+
require.NoError(t, err)
1736+
1737+
_, err = c.CreateRole(role)
1738+
require.NoError(t, err)
1739+
_, err = c.CreateRoleBinding(roleBinding)
1740+
require.NoError(t, err)
1741+
1742+
log("wait for CSV to succeeed")
1743+
err = wait.Poll(pollInterval, pollDuration, func() (bool, error) {
1744+
fetched, err := crc.OperatorsV1alpha1().ClusterServiceVersions(newNamespaceName).Get(createdCSV.GetName(), metav1.GetOptions{})
1745+
if err != nil {
1746+
return false, err
1747+
}
1748+
log(fmt.Sprintf("%s (%s): %s", fetched.Status.Phase, fetched.Status.Reason, fetched.Status.Message))
1749+
return csvSucceededChecker(fetched), nil
1750+
})
1751+
require.NoError(t, err)
1752+
}
1753+
1754+
func TestOperatorGroupInsufficientPermissionsResolveViaServiceAccountRemoval(t *testing.T) {
1755+
defer cleaner.NotifyTestComplete(t, true)
1756+
1757+
log := func(s string) {
1758+
t.Logf("%s: %s", time.Now().Format("15:04:05.9999"), s)
1759+
}
1760+
1761+
c := newKubeClient(t)
1762+
crc := newCRClient(t)
1763+
csvName := genName("another-csv-")
1764+
1765+
newNamespaceName := genName(testNamespace + "-")
1766+
1767+
_, err := c.KubernetesInterface().CoreV1().Namespaces().Create(&corev1.Namespace{
1768+
ObjectMeta: metav1.ObjectMeta{
1769+
Name: newNamespaceName,
1770+
},
1771+
})
1772+
require.NoError(t, err)
1773+
defer func() {
1774+
err = c.KubernetesInterface().CoreV1().Namespaces().Delete(newNamespaceName, &metav1.DeleteOptions{})
1775+
require.NoError(t, err)
1776+
}()
1777+
1778+
log("Creating CRD")
1779+
mainCRDPlural := genName("opgroup")
1780+
mainCRD := newCRD(mainCRDPlural)
1781+
cleanupCRD, err := createCRD(c, mainCRD)
1782+
require.NoError(t, err)
1783+
defer cleanupCRD()
1784+
1785+
log("Creating operator group")
1786+
serviceAccountName := genName("nginx-sa")
1787+
// intentionally creating an operator group without a service account already existing
1788+
operatorGroup := v1.OperatorGroup{
1789+
ObjectMeta: metav1.ObjectMeta{
1790+
Name: genName("e2e-operator-group-"),
1791+
Namespace: newNamespaceName,
1792+
},
1793+
Spec: v1.OperatorGroupSpec{
1794+
ServiceAccountName: serviceAccountName,
1795+
TargetNamespaces: []string{newNamespaceName},
1796+
},
1797+
}
1798+
_, err = crc.OperatorsV1().OperatorGroups(newNamespaceName).Create(&operatorGroup)
1799+
require.NoError(t, err)
1800+
1801+
log("Creating CSV")
1802+
1803+
// Create a new NamedInstallStrategy
1804+
deploymentName := genName("operator-deployment")
1805+
namedStrategy := newNginxInstallStrategy(deploymentName, nil, nil)
1806+
1807+
aCSV := newCSV(csvName, newNamespaceName, "", semver.MustParse("0.0.0"), []apiextensions.CustomResourceDefinition{mainCRD}, nil, namedStrategy)
1808+
createdCSV, err := crc.OperatorsV1alpha1().ClusterServiceVersions(newNamespaceName).Create(&aCSV)
1809+
require.NoError(t, err)
1810+
1811+
serviceAccount := &corev1.ServiceAccount{
1812+
ObjectMeta: metav1.ObjectMeta{
1813+
Namespace: newNamespaceName,
1814+
Name: serviceAccountName,
1815+
},
1816+
}
1817+
ownerutil.AddNonBlockingOwner(serviceAccount, createdCSV)
1818+
err = ownerutil.AddOwnerLabels(serviceAccount, createdCSV)
1819+
require.NoError(t, err)
1820+
1821+
_, err = c.CreateServiceAccount(serviceAccount)
1822+
require.NoError(t, err)
1823+
1824+
log("wait for CSV to fail")
1825+
err = wait.Poll(pollInterval, pollDuration, func() (bool, error) {
1826+
fetched, err := crc.OperatorsV1alpha1().ClusterServiceVersions(newNamespaceName).Get(createdCSV.GetName(), metav1.GetOptions{})
1827+
if err != nil {
1828+
return false, err
1829+
}
1830+
log(fmt.Sprintf("%s (%s): %s", fetched.Status.Phase, fetched.Status.Reason, fetched.Status.Message))
1831+
return csvFailedChecker(fetched), nil
1832+
})
1833+
require.NoError(t, err)
1834+
1835+
// now remove operator group specified service account
1836+
createdOpGroup, err := crc.OperatorsV1().OperatorGroups(newNamespaceName).Get(operatorGroup.GetName(), metav1.GetOptions{})
1837+
require.NoError(t, err)
1838+
createdOpGroup.Spec.ServiceAccountName = ""
1839+
_, err = crc.OperatorsV1().OperatorGroups(newNamespaceName).Update(createdOpGroup)
1840+
require.NoError(t, err)
1841+
1842+
log("wait for CSV to succeeed")
1843+
err = wait.Poll(pollInterval, pollDuration, func() (bool, error) {
1844+
fetched, err := crc.OperatorsV1alpha1().ClusterServiceVersions(newNamespaceName).Get(createdCSV.GetName(), metav1.GetOptions{})
1845+
if err != nil {
1846+
return false, err
1847+
}
1848+
log(fmt.Sprintf("%s (%s): %s", fetched.Status.Phase, fetched.Status.Reason, fetched.Status.Message))
1849+
return csvSucceededChecker(fetched), nil
1850+
})
1851+
require.NoError(t, err)
1852+
}

0 commit comments

Comments
 (0)