// Copyright 2021 Google LLC
//
// 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.

package devicepolicy

// Utility functions for manipulating device policy.

import (
	"crypto"
	"crypto/rand"
	"crypto/rsa"
	"crypto/sha1"
	"io/ioutil"
	"os"
	"time"

	"policy-manager/pkg/sysapi"
	pmpb "policy-manager/protos"
	pb "policy-manager/third_party/chromium/devicepolicyproto"

	"github.com/golang/protobuf/proto"
)

// DevicePolicy is an opaque type that represents the device policy. This hides
// the complexity of the device policy protobufs from the users.
type DevicePolicy struct {
	metricsEnabled *pb.MetricsEnabledProto
	// InstanceConfig is an InstanceConfigProto that manages the device policy file.
	instanceConfig *pmpb.InstanceConfig
}

// hashPolicyData hashes the given policy data using SHA1.
func hashPolicyData(data []byte) []byte {
	h := sha1.New()
	h.Write(data)
	return h.Sum(nil)
}

// generateDevicePolicy generates a signed PolicyFetchResponse protobuf that can
// be written to disk. The provided private key will be used to generate the
// signature.
func (p *DevicePolicy) generateDevicePolicy(key *rsa.PrivateKey) (*pb.PolicyFetchResponse, error) {
	// Generate ChromeDeviceSettingsProto.
	chromeDeviceSettings := pb.ChromeDeviceSettingsProto{
		MetricsEnabled: p.metricsEnabled,
	}
	chromeDeviceSettingsBytes, err := proto.Marshal(&chromeDeviceSettings)
	if err != nil {
		return nil, err
	}

	// Generate PolicyData.
	policyData := pb.PolicyData{
		PolicyType:       proto.String(policyType),
		Timestamp:        proto.Int64(time.Now().Unix()),
		PolicyValue:      chromeDeviceSettingsBytes,
		PublicKeyVersion: proto.Int32(1),
	}
	policyDataBytes, err := proto.Marshal(&policyData)
	if err != nil {
		return nil, err
	}

	// Hash policyData.
	hash := hashPolicyData(policyDataBytes)

	// Sign PolicyData.
	policyDataSig, err := rsa.SignPKCS1v15(rand.Reader, key, crypto.SHA1, hash)
	if err != nil {
		return nil, err
	}

	// Generate PolicyFetchResponse.
	policyFetchResponse := &pb.PolicyFetchResponse{
		PolicyData:          policyDataBytes,
		PolicyDataSignature: policyDataSig,
	}

	return policyFetchResponse, nil
}

// SetFromInstanceConfig sets the settings from the instance config to the
// DevicePolicy.
// Returns 'true' if this resulted in any change in device policy, otherwise false.
func (p *DevicePolicy) SetFromInstanceConfig(config *pmpb.InstanceConfig) bool {
	if config == nil {
		return false
	}
	policyChanged := false

	instanceConfig := &pmpb.InstanceConfig{
		UpdateStrategy:      proto.String(config.GetUpdateStrategy()),
		MetricsEnabled:      proto.Bool(config.GetMetricsEnabled()),
		HealthMonitorConfig: proto.Clone(config.HealthMonitorConfig).(*pmpb.HealthMonitorConfig),
	}

	metricsEnabled := &pb.MetricsEnabledProto{
		MetricsEnabled: proto.Bool(config.GetMetricsEnabled()),
	}

	if p.instanceConfig == nil || !proto.Equal(instanceConfig, p.instanceConfig) {
		policyChanged = true
	}

	p.instanceConfig = instanceConfig
	p.metricsEnabled = metricsEnabled
	return policyChanged
}

// ToInstanceConfig converts the DevicePolicy into InstanceConfig proto
func (p *DevicePolicy) ToInstanceConfig(config *pmpb.InstanceConfig) {
	if config == nil {
		return
	}

	if p.instanceConfig != nil {
		config.UpdateStrategy = proto.String(p.instanceConfig.GetUpdateStrategy())
		config.MetricsEnabled = proto.Bool(p.instanceConfig.GetMetricsEnabled())
		config.HealthMonitorConfig = proto.Clone(p.instanceConfig.HealthMonitorConfig).(*pmpb.HealthMonitorConfig)
	}
}

// WriteFile writes the policy to disk. The policy will atomically replace the existing policy.
func (p *DevicePolicy) SignAndWrite(key *rsa.PrivateKey, devicePolicyFile string, instanceConfigFile string) error {
	// Generate policy protobuf.
	policyFetchResponse, err := p.generateDevicePolicy(key)
	if err != nil {
		return nil
	}
	policyBytes, err := proto.Marshal(policyFetchResponse)
	if err != nil {
		return err
	}
	// Generate policy protobuf.
	instanceConfigBytes, err := proto.Marshal(p.instanceConfig)
	if err != nil {
		return err
	}
	// Write the policy file atomically.
	if err := sysapi.AtomicWriteFile(devicePolicyFile, policyBytes, configFilePerm); err != nil {
		return err
	}
	// Write the policy file atomically.
	if err := sysapi.AtomicWriteFile(instanceConfigFile, instanceConfigBytes, configFilePerm); err != nil {
		return err
	}
	return nil
}

// ReadPolicyFromDisk reads the device policy from disk.
// No error is returned for missing policy file.
func (p *DevicePolicy) ReadPolicyFromDisk(instanceConfigFile string) error {
	// Check if cos device policy file exists
	if _, err := os.Stat(instanceConfigFile); os.IsNotExist(err) {
		return nil
	}

	// Read the policy file and convert it to protobuf format.
	instanceConfigBytes, err := ioutil.ReadFile(instanceConfigFile)
	if err != nil {
		return err
	}

	// Unmarshal InstanceConfig
	var instanceConfig pmpb.InstanceConfig
	err = proto.Unmarshal(instanceConfigBytes, &instanceConfig)
	if err != nil {
		return err
	}

	// Store the relevant protobufs in memory.
	p.instanceConfig = &instanceConfig

	return nil
}
