blob: 8a75455072716f7d532fadc228678bebd905037a [file] [log] [blame]
// Copyright 2019 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
// Package ad provides Active Directory related tests (Kerberos, Chrome OS
// Active Directory integration aka. Chromad).
package ad
import (
"context"
"github.com/golang/protobuf/proto"
"github.com/google/go-cmp/cmp"
"google.golang.org/protobuf/testing/protocmp"
kp "chromiumos/system_api/kerberos_proto"
"chromiumos/tast/local/bundles/cros/ad/kerberos"
"chromiumos/tast/testing"
)
func init() {
testing.AddTest(&testing.Test{
Func: KerberosDaemon,
Desc: "Verifies that the Kerberos system dameon works as expected",
Contacts: []string{
"fsandrade@chromium.org",
"chromeos-commercial-identity@google.com",
},
Attr: []string{"group:mainline", "informational"},
})
}
// KerberosDaemon tests basic functionality of the Kerberos system daemon.
func KerberosDaemon(ctx context.Context, s *testing.State) {
const (
user = "user@EXAMPLE.COM"
password = "fakepw123"
validConfig = "[libdefaults]\nforwardable=false"
invalidConfig = "[libdefaults]\nallow_weak_crypto=true"
)
k, err := kerberos.New(ctx)
if err != nil {
s.Fatal("Failed to create Kerberos binding: ", err)
}
// Wipe any existing accounts from previous tests.
clearResp, err := k.ClearAccounts(ctx)
if err != nil {
s.Fatal("ClearAccounts failed. D-Bus error: ", err)
}
if *clearResp.Error != kp.ErrorType_ERROR_NONE {
s.Fatalf("ClearAccounts failed unexpectedly with error %q", clearResp.Error.String())
}
// Add an account.
addResp, err := k.AddAccount(ctx, user)
if err != nil {
s.Fatal("AddAccount failed. D-Bus error: ", err)
}
if *addResp.Error != kp.ErrorType_ERROR_NONE {
s.Fatalf("AddAccount failed unexpectedly with error %q", addResp.Error.String())
}
// Set a valid config on the account.
setResp, err := k.SetConfig(ctx, user, validConfig)
if err != nil {
s.Fatal("SetConfig failed. D-Bus error: ", err)
}
if *setResp.Error != kp.ErrorType_ERROR_NONE {
s.Fatalf("SetConfig failed unexpectedly with error %q", setResp.Error.String())
}
// Set an invalid config on the account.
setResp, err = k.SetConfig(ctx, user, invalidConfig)
if err != nil {
s.Fatal("SetConfig failed. D-Bus error: ", err)
}
if *setResp.Error != kp.ErrorType_ERROR_BAD_CONFIG {
s.Fatalf("SetConfig returned unexpected error: got %q; want \"ErrorType_ERROR_BAD_CONFIG\"", setResp.Error.String())
}
// Find out why the config was invalid.
validateResp, err := k.ValidateConfig(ctx, invalidConfig)
if err != nil {
s.Fatal("ValidateConfig failed. D-Bus error: ", err)
}
badConfigError := kp.ErrorType_ERROR_BAD_CONFIG
badConfigErrorCode := kp.ConfigErrorCode_CONFIG_ERROR_KEY_NOT_SUPPORTED
expectedResp := &kp.ValidateConfigResponse{
Error: &badConfigError,
ErrorInfo: &kp.ConfigErrorInfo{
Code: &badConfigErrorCode,
LineIndex: proto.Int32(1),
},
}
if diff := cmp.Diff(validateResp, expectedResp, protocmp.Transform()); diff != "" {
s.Fatal("ValidateConfigResponse message mismatch (-got +want): ", diff)
}
// Acquire a Kerberos ticket.
acquireTgtResp, err := k.AcquireKerberosTgt(ctx, user, password /*rememberPassword=*/, true /*useLoginPassword=*/, false)
if err != nil {
s.Fatal("AcquireKerberosTgt failed. D-Bus error: ", err)
}
if *acquireTgtResp.Error != kp.ErrorType_ERROR_CONTACTING_KDC_FAILED {
s.Fatalf("AcquireKerberosTgt returned unexpected error: got %q; want \"ErrorType_ERROR_CONTACTING_KDC_FAILED\"", acquireTgtResp.Error.String())
}
// List account and verify the data.
listResp, err := k.ListAccounts(ctx)
if err != nil {
s.Fatal("ListAccounts failed. D-Bus error: ", err)
}
if *listResp.Error != kp.ErrorType_ERROR_NONE {
s.Fatalf("ListAccounts failed unexpectedly with error %q", listResp.Error.String())
}
if len(listResp.Accounts) != 1 {
s.Fatalf("Unexpected accounts len: got %d; want 1", len(listResp.Accounts))
}
acc := listResp.Accounts[0]
expectedAcc := &kp.Account{
PrincipalName: proto.String(user),
Krb5Conf: []byte(validConfig),
TgtValiditySeconds: nil,
TgtRenewalSeconds: nil,
IsManaged: proto.Bool(false),
PasswordWasRemembered: proto.Bool(true),
UseLoginPassword: proto.Bool(false),
}
if diff := cmp.Diff(acc, expectedAcc, protocmp.Transform()); diff != "" {
s.Fatal("Account message mismatch (-got +want): ", diff)
}
// Get files.
getFilesResp, err := k.GetKerberosFiles(ctx, user)
if err != nil {
s.Fatal("GetKerberosFiles failed. D-Bus error: ", err)
}
if *getFilesResp.Error != kp.ErrorType_ERROR_NONE {
s.Fatalf("GetKerberosFiles failed unexpectedly with error %q", getFilesResp.Error.String())
}
if len(getFilesResp.Files.Krb5Conf) != 0 {
s.Fatalf("Unexpected Krb5Conf length: got %d; want 0", len(getFilesResp.Files.Krb5Conf))
}
if len(getFilesResp.Files.Krb5Cc) != 0 {
s.Fatalf("Unexpected Krb5Cc length: got %d; want 0", len(getFilesResp.Files.Krb5Cc))
}
// Remove account again.
removeResp, err := k.RemoveAccount(ctx, user)
if err != nil {
s.Fatal("RemoveAccount failed. D-Bus error: ", err)
}
if *removeResp.Error != kp.ErrorType_ERROR_NONE {
s.Fatalf("RemoveAccount failed unexpectedly with error %q", removeResp.Error.String())
}
// Verify that account list is empty.
listResp, err = k.ListAccounts(ctx)
if err != nil {
s.Fatal("ListAccounts failed. D-Bus error: ", err)
}
if *listResp.Error != kp.ErrorType_ERROR_NONE {
s.Fatalf("ListAccounts failed unexpectedly with error %q", listResp.Error.String())
}
if len(listResp.Accounts) != 0 {
s.Fatalf("Unexpected accounts len: got %d; want 0", len(listResp.Accounts))
}
}